@fairfox/polly 0.15.1 → 0.15.4
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.
- package/dist/tools/analysis/src/extract/handlers.d.ts +72 -0
- package/dist/tools/teach/src/cli.js +375 -35
- package/dist/tools/teach/src/cli.js.map +3 -3
- package/dist/tools/teach/src/index.js +375 -35
- package/dist/tools/teach/src/index.js.map +3 -3
- package/dist/tools/verify/src/cli.js +521 -73
- package/dist/tools/verify/src/cli.js.map +4 -4
- package/dist/tools/verify/src/config.d.ts +1 -1
- package/dist/tools/verify/src/config.js +21 -1
- package/dist/tools/verify/src/config.js.map +3 -3
- package/dist/tools/visualize/src/cli.js +375 -35
- package/dist/tools/visualize/src/cli.js.map +3 -3
- package/package.json +1 -1
|
@@ -236664,6 +236664,7 @@ class HandlerExtractor {
|
|
|
236664
236664
|
relationshipExtractor;
|
|
236665
236665
|
analyzedFiles;
|
|
236666
236666
|
packageRoot;
|
|
236667
|
+
warnings;
|
|
236667
236668
|
constructor(tsConfigPath) {
|
|
236668
236669
|
this.project = new import_ts_morph4.Project({
|
|
236669
236670
|
tsConfigFilePath: tsConfigPath
|
|
@@ -236671,8 +236672,27 @@ class HandlerExtractor {
|
|
|
236671
236672
|
this.typeGuardCache = new WeakMap;
|
|
236672
236673
|
this.relationshipExtractor = new RelationshipExtractor;
|
|
236673
236674
|
this.analyzedFiles = new Set;
|
|
236675
|
+
this.warnings = [];
|
|
236674
236676
|
this.packageRoot = this.findPackageRoot(tsConfigPath);
|
|
236675
236677
|
}
|
|
236678
|
+
warnUnsupportedPattern(pattern, location2, suggestion) {
|
|
236679
|
+
const exists = this.warnings.some((w) => w.pattern === pattern && w.location === location2);
|
|
236680
|
+
if (!exists) {
|
|
236681
|
+
this.warnings.push({
|
|
236682
|
+
type: "unsupported_pattern",
|
|
236683
|
+
pattern,
|
|
236684
|
+
location: location2,
|
|
236685
|
+
suggestion
|
|
236686
|
+
});
|
|
236687
|
+
}
|
|
236688
|
+
}
|
|
236689
|
+
getNodeLocation(node) {
|
|
236690
|
+
const sourceFile = node.getSourceFile();
|
|
236691
|
+
const lineAndCol = sourceFile.getLineAndColumnAtPos(node.getStart());
|
|
236692
|
+
const filePath = sourceFile.getFilePath();
|
|
236693
|
+
const relativePath = filePath.startsWith(this.packageRoot) ? filePath.substring(this.packageRoot.length + 1) : filePath;
|
|
236694
|
+
return `${relativePath}:${lineAndCol.line}`;
|
|
236695
|
+
}
|
|
236676
236696
|
findPackageRoot(tsConfigPath) {
|
|
236677
236697
|
let dir = tsConfigPath.substring(0, tsConfigPath.lastIndexOf("/"));
|
|
236678
236698
|
while (dir.length > 1) {
|
|
@@ -236696,6 +236716,7 @@ class HandlerExtractor {
|
|
|
236696
236716
|
const invalidMessageTypes = new Set;
|
|
236697
236717
|
const stateConstraints = [];
|
|
236698
236718
|
const verifiedStates = [];
|
|
236719
|
+
this.warnings = [];
|
|
236699
236720
|
const allSourceFiles = this.project.getSourceFiles();
|
|
236700
236721
|
const entryPoints = allSourceFiles.filter((f) => this.isWithinPackage(f.getFilePath()));
|
|
236701
236722
|
this.debugLogSourceFiles(allSourceFiles, entryPoints);
|
|
@@ -236730,7 +236751,8 @@ class HandlerExtractor {
|
|
|
236730
236751
|
handlers,
|
|
236731
236752
|
messageTypes,
|
|
236732
236753
|
stateConstraints,
|
|
236733
|
-
verifiedStates
|
|
236754
|
+
verifiedStates,
|
|
236755
|
+
warnings: this.warnings
|
|
236734
236756
|
};
|
|
236735
236757
|
}
|
|
236736
236758
|
analyzeFileAndImports(sourceFile, handlers, messageTypes, invalidMessageTypes, stateConstraints, verifiedStates) {
|
|
@@ -236960,46 +236982,364 @@ class HandlerExtractor {
|
|
|
236960
236982
|
if (!import_ts_morph4.Node.isPropertyAccessExpression(left))
|
|
236961
236983
|
return;
|
|
236962
236984
|
const fieldPath = this.getPropertyPath(left);
|
|
236963
|
-
if (
|
|
236964
|
-
const field = fieldPath.substring(6);
|
|
236965
|
-
const value = this.extractValue(right);
|
|
236966
|
-
if (value !== undefined) {
|
|
236967
|
-
assignments.push({ field, value });
|
|
236968
|
-
}
|
|
236985
|
+
if (this.tryExtractStateFieldPattern(fieldPath, right, assignments))
|
|
236969
236986
|
return;
|
|
236970
|
-
|
|
236971
|
-
|
|
236972
|
-
if (
|
|
236973
|
-
|
|
236974
|
-
|
|
236975
|
-
if (value !== undefined) {
|
|
236976
|
-
assignments.push({ field, value });
|
|
236977
|
-
}
|
|
236987
|
+
if (this.tryExtractSignalNestedFieldPattern(fieldPath, right, assignments))
|
|
236988
|
+
return;
|
|
236989
|
+
if (this.tryExtractSignalObjectPattern(fieldPath, right, assignments))
|
|
236990
|
+
return;
|
|
236991
|
+
if (this.tryExtractSignalArrayPattern(fieldPath, right, assignments))
|
|
236978
236992
|
return;
|
|
236993
|
+
if (this.tryExtractSignalMethodPattern(fieldPath, right, assignments))
|
|
236994
|
+
return;
|
|
236995
|
+
if (this.tryExtractSetConstructorPattern(fieldPath, right, assignments))
|
|
236996
|
+
return;
|
|
236997
|
+
this.tryExtractMapConstructorPattern(fieldPath, right, assignments);
|
|
236998
|
+
}
|
|
236999
|
+
tryExtractStateFieldPattern(fieldPath, right, assignments) {
|
|
237000
|
+
if (!fieldPath.startsWith("state."))
|
|
237001
|
+
return false;
|
|
237002
|
+
const field = fieldPath.substring(6);
|
|
237003
|
+
const value = this.extractValue(right);
|
|
237004
|
+
if (value !== undefined) {
|
|
237005
|
+
assignments.push({ field, value });
|
|
236979
237006
|
}
|
|
236980
|
-
|
|
236981
|
-
|
|
237007
|
+
return true;
|
|
237008
|
+
}
|
|
237009
|
+
tryExtractSignalNestedFieldPattern(fieldPath, right, assignments) {
|
|
237010
|
+
const valueFieldMatch = fieldPath.match(/^([a-zA-Z_][a-zA-Z0-9_]*)\.value\.(.+)$/);
|
|
237011
|
+
if (!valueFieldMatch?.[1] || !valueFieldMatch?.[2])
|
|
237012
|
+
return false;
|
|
237013
|
+
const signalName = valueFieldMatch[1];
|
|
237014
|
+
const fieldName = valueFieldMatch[2];
|
|
237015
|
+
const value = this.extractValue(right);
|
|
237016
|
+
if (value !== undefined) {
|
|
237017
|
+
assignments.push({ field: `${signalName}_${fieldName}`, value });
|
|
236982
237018
|
}
|
|
237019
|
+
return true;
|
|
236983
237020
|
}
|
|
236984
|
-
|
|
236985
|
-
if (!import_ts_morph4.Node.isObjectLiteralExpression(
|
|
237021
|
+
tryExtractSignalObjectPattern(fieldPath, right, assignments) {
|
|
237022
|
+
if (!fieldPath.endsWith(".value") || !import_ts_morph4.Node.isObjectLiteralExpression(right))
|
|
237023
|
+
return false;
|
|
237024
|
+
const signalName = fieldPath.slice(0, -6);
|
|
237025
|
+
if (this.isSpreadUpdatePattern(right, fieldPath)) {
|
|
237026
|
+
this.extractSpreadUpdateAssignments(right, assignments, signalName);
|
|
237027
|
+
} else {
|
|
237028
|
+
this.extractObjectLiteralAssignments(right, assignments, signalName);
|
|
237029
|
+
}
|
|
237030
|
+
return true;
|
|
237031
|
+
}
|
|
237032
|
+
isSpreadUpdatePattern(objectLiteral, fieldPath) {
|
|
237033
|
+
const properties = objectLiteral.getProperties();
|
|
237034
|
+
if (properties.length === 0)
|
|
237035
|
+
return false;
|
|
237036
|
+
const firstProp = properties[0];
|
|
237037
|
+
if (!firstProp || !import_ts_morph4.Node.isSpreadAssignment(firstProp))
|
|
237038
|
+
return false;
|
|
237039
|
+
const spreadExpr = firstProp.getExpression();
|
|
237040
|
+
if (!spreadExpr)
|
|
237041
|
+
return false;
|
|
237042
|
+
return this.getPropertyPath(spreadExpr) === fieldPath;
|
|
237043
|
+
}
|
|
237044
|
+
tryExtractSignalArrayPattern(fieldPath, right, assignments) {
|
|
237045
|
+
if (!fieldPath.endsWith(".value") || !import_ts_morph4.Node.isArrayLiteralExpression(right))
|
|
237046
|
+
return false;
|
|
237047
|
+
const signalName = fieldPath.slice(0, -6);
|
|
237048
|
+
const arrayAssignment = this.extractArraySpreadOperation(right, fieldPath, signalName);
|
|
237049
|
+
if (arrayAssignment) {
|
|
237050
|
+
assignments.push(arrayAssignment);
|
|
237051
|
+
}
|
|
237052
|
+
return true;
|
|
237053
|
+
}
|
|
237054
|
+
tryExtractSignalMethodPattern(fieldPath, right, assignments) {
|
|
237055
|
+
if (!fieldPath.endsWith(".value") || !import_ts_morph4.Node.isCallExpression(right))
|
|
237056
|
+
return false;
|
|
237057
|
+
const signalName = fieldPath.slice(0, -6);
|
|
237058
|
+
this.checkForMutatingCollectionMethods(right);
|
|
237059
|
+
const methodAssignment = this.extractArrayMethodOperation(right, fieldPath, signalName);
|
|
237060
|
+
if (methodAssignment) {
|
|
237061
|
+
assignments.push(methodAssignment);
|
|
237062
|
+
}
|
|
237063
|
+
return true;
|
|
237064
|
+
}
|
|
237065
|
+
checkForMutatingCollectionMethods(callExpr) {
|
|
237066
|
+
const expression = callExpr.getExpression();
|
|
237067
|
+
if (!import_ts_morph4.Node.isPropertyAccessExpression(expression))
|
|
236986
237068
|
return;
|
|
236987
|
-
|
|
236988
|
-
|
|
236989
|
-
|
|
236990
|
-
|
|
236991
|
-
|
|
236992
|
-
|
|
236993
|
-
|
|
236994
|
-
|
|
236995
|
-
|
|
237069
|
+
const methodName = expression.getName();
|
|
237070
|
+
const sourceExpr = expression.getExpression();
|
|
237071
|
+
const setMethods = ["add", "delete", "clear"];
|
|
237072
|
+
if (setMethods.includes(methodName)) {
|
|
237073
|
+
const sourceText = sourceExpr.getText();
|
|
237074
|
+
if (sourceText.includes("Set") || this.looksLikeSetOrMap(sourceExpr, "Set")) {
|
|
237075
|
+
this.warnUnsupportedPattern(`set.${methodName}()`, this.getNodeLocation(callExpr), `Set.${methodName}() mutates in place. Use: new Set([...set, item]) for add, new Set([...set].filter(...)) for delete.`);
|
|
237076
|
+
}
|
|
237077
|
+
}
|
|
237078
|
+
const mapMethods = ["set", "delete", "clear"];
|
|
237079
|
+
if (mapMethods.includes(methodName)) {
|
|
237080
|
+
const sourceText = sourceExpr.getText();
|
|
237081
|
+
if (sourceText.includes("Map") || this.looksLikeSetOrMap(sourceExpr, "Map")) {
|
|
237082
|
+
this.warnUnsupportedPattern(`map.${methodName}()`, this.getNodeLocation(callExpr), `Map.${methodName}() mutates in place. Use: new Map([...map, [key, value]]) for set, new Map([...map].filter(...)) for delete.`);
|
|
237083
|
+
}
|
|
237084
|
+
}
|
|
237085
|
+
}
|
|
237086
|
+
looksLikeSetOrMap(expr, collectionType) {
|
|
237087
|
+
const text = expr.getText().toLowerCase();
|
|
237088
|
+
return text.includes(collectionType.toLowerCase());
|
|
237089
|
+
}
|
|
237090
|
+
tryExtractSetConstructorPattern(fieldPath, right, assignments) {
|
|
237091
|
+
if (!fieldPath.endsWith(".value") || !import_ts_morph4.Node.isNewExpression(right))
|
|
237092
|
+
return false;
|
|
237093
|
+
const constructorExpr = right.getExpression();
|
|
237094
|
+
if (!import_ts_morph4.Node.isIdentifier(constructorExpr) || constructorExpr.getText() !== "Set")
|
|
237095
|
+
return false;
|
|
237096
|
+
const signalName = fieldPath.slice(0, -6);
|
|
237097
|
+
const setAssignment = this.extractSetOperation(right, fieldPath, signalName);
|
|
237098
|
+
if (setAssignment) {
|
|
237099
|
+
assignments.push(setAssignment);
|
|
237100
|
+
}
|
|
237101
|
+
return true;
|
|
237102
|
+
}
|
|
237103
|
+
tryExtractMapConstructorPattern(fieldPath, right, assignments) {
|
|
237104
|
+
if (!fieldPath.endsWith(".value") || !import_ts_morph4.Node.isNewExpression(right))
|
|
237105
|
+
return false;
|
|
237106
|
+
const constructorExpr = right.getExpression();
|
|
237107
|
+
if (!import_ts_morph4.Node.isIdentifier(constructorExpr) || constructorExpr.getText() !== "Map")
|
|
237108
|
+
return false;
|
|
237109
|
+
const signalName = fieldPath.slice(0, -6);
|
|
237110
|
+
const mapAssignment = this.extractMapOperation(right, fieldPath, signalName);
|
|
237111
|
+
if (mapAssignment) {
|
|
237112
|
+
assignments.push(mapAssignment);
|
|
237113
|
+
}
|
|
237114
|
+
return true;
|
|
237115
|
+
}
|
|
237116
|
+
extractSetOperation(newExpr, fieldPath, signalName) {
|
|
237117
|
+
const args = newExpr.getArguments();
|
|
237118
|
+
if (args.length === 0) {
|
|
237119
|
+
return { field: signalName, value: "{}" };
|
|
237120
|
+
}
|
|
237121
|
+
const firstArg = args[0];
|
|
237122
|
+
if (!firstArg)
|
|
237123
|
+
return null;
|
|
237124
|
+
if (import_ts_morph4.Node.isArrayLiteralExpression(firstArg)) {
|
|
237125
|
+
return this.extractSetArrayOperation(firstArg, fieldPath, signalName);
|
|
237126
|
+
}
|
|
237127
|
+
if (import_ts_morph4.Node.isCallExpression(firstArg)) {
|
|
237128
|
+
return this.extractSetMethodChainOperation(firstArg, fieldPath, signalName);
|
|
237129
|
+
}
|
|
237130
|
+
return null;
|
|
237131
|
+
}
|
|
237132
|
+
extractSetArrayOperation(arrayLiteral, fieldPath, signalName) {
|
|
237133
|
+
const elements = arrayLiteral.getElements();
|
|
237134
|
+
if (elements.length < 1)
|
|
237135
|
+
return null;
|
|
237136
|
+
const firstElement = elements[0];
|
|
237137
|
+
const lastElement = elements[elements.length - 1];
|
|
237138
|
+
if (firstElement && import_ts_morph4.Node.isSpreadElement(firstElement)) {
|
|
237139
|
+
const spreadExpr = firstElement.getExpression();
|
|
237140
|
+
if (spreadExpr && this.getPropertyPath(spreadExpr) === fieldPath) {
|
|
237141
|
+
return { field: signalName, value: "@ \\union {payload}" };
|
|
237142
|
+
}
|
|
237143
|
+
}
|
|
237144
|
+
if (lastElement && import_ts_morph4.Node.isSpreadElement(lastElement)) {
|
|
237145
|
+
const spreadExpr = lastElement.getExpression();
|
|
237146
|
+
if (spreadExpr && this.getPropertyPath(spreadExpr) === fieldPath) {
|
|
237147
|
+
return { field: signalName, value: "{payload} \\union @" };
|
|
237148
|
+
}
|
|
237149
|
+
}
|
|
237150
|
+
return null;
|
|
237151
|
+
}
|
|
237152
|
+
extractSetMethodChainOperation(callExpr, fieldPath, signalName) {
|
|
237153
|
+
const expression = callExpr.getExpression();
|
|
237154
|
+
if (!import_ts_morph4.Node.isPropertyAccessExpression(expression))
|
|
237155
|
+
return null;
|
|
237156
|
+
const methodName = expression.getName();
|
|
237157
|
+
const sourceExpr = expression.getExpression();
|
|
237158
|
+
if (methodName === "filter" && import_ts_morph4.Node.isArrayLiteralExpression(sourceExpr)) {
|
|
237159
|
+
const elements = sourceExpr.getElements();
|
|
237160
|
+
if (elements.length === 1) {
|
|
237161
|
+
const spreadEl = elements[0];
|
|
237162
|
+
if (spreadEl && import_ts_morph4.Node.isSpreadElement(spreadEl)) {
|
|
237163
|
+
const spreadExpr = spreadEl.getExpression();
|
|
237164
|
+
if (spreadExpr && this.getPropertyPath(spreadExpr) === fieldPath) {
|
|
237165
|
+
return { field: signalName, value: "@ \\ {payload}" };
|
|
237166
|
+
}
|
|
236996
237167
|
}
|
|
236997
237168
|
}
|
|
236998
|
-
|
|
236999
|
-
|
|
237000
|
-
|
|
237169
|
+
}
|
|
237170
|
+
return null;
|
|
237171
|
+
}
|
|
237172
|
+
extractMapOperation(newExpr, fieldPath, signalName) {
|
|
237173
|
+
const args = newExpr.getArguments();
|
|
237174
|
+
if (args.length === 0) {
|
|
237175
|
+
return { field: signalName, value: "<<>>" };
|
|
237176
|
+
}
|
|
237177
|
+
const firstArg = args[0];
|
|
237178
|
+
if (!firstArg)
|
|
237179
|
+
return null;
|
|
237180
|
+
if (import_ts_morph4.Node.isArrayLiteralExpression(firstArg)) {
|
|
237181
|
+
return this.extractMapArrayOperation(firstArg, fieldPath, signalName);
|
|
237182
|
+
}
|
|
237183
|
+
if (import_ts_morph4.Node.isCallExpression(firstArg)) {
|
|
237184
|
+
return this.extractMapMethodChainOperation(firstArg, fieldPath, signalName);
|
|
237185
|
+
}
|
|
237186
|
+
return null;
|
|
237187
|
+
}
|
|
237188
|
+
extractMapArrayOperation(arrayLiteral, fieldPath, signalName) {
|
|
237189
|
+
const elements = arrayLiteral.getElements();
|
|
237190
|
+
if (elements.length < 1)
|
|
237191
|
+
return null;
|
|
237192
|
+
const firstElement = elements[0];
|
|
237193
|
+
if (firstElement && import_ts_morph4.Node.isSpreadElement(firstElement)) {
|
|
237194
|
+
const spreadExpr = firstElement.getExpression();
|
|
237195
|
+
if (spreadExpr && this.getPropertyPath(spreadExpr) === fieldPath) {
|
|
237196
|
+
return { field: signalName, value: "[@ EXCEPT ![payload.key] = payload.value]" };
|
|
237197
|
+
}
|
|
237198
|
+
}
|
|
237199
|
+
return null;
|
|
237200
|
+
}
|
|
237201
|
+
extractMapMethodChainOperation(callExpr, fieldPath, signalName) {
|
|
237202
|
+
const expression = callExpr.getExpression();
|
|
237203
|
+
if (!import_ts_morph4.Node.isPropertyAccessExpression(expression))
|
|
237204
|
+
return null;
|
|
237205
|
+
const methodName = expression.getName();
|
|
237206
|
+
const sourceExpr = expression.getExpression();
|
|
237207
|
+
if (methodName === "filter" && import_ts_morph4.Node.isArrayLiteralExpression(sourceExpr)) {
|
|
237208
|
+
const elements = sourceExpr.getElements();
|
|
237209
|
+
if (elements.length === 1) {
|
|
237210
|
+
const spreadEl = elements[0];
|
|
237211
|
+
if (spreadEl && import_ts_morph4.Node.isSpreadElement(spreadEl)) {
|
|
237212
|
+
const spreadExpr = spreadEl.getExpression();
|
|
237213
|
+
if (spreadExpr && this.getPropertyPath(spreadExpr) === fieldPath) {
|
|
237214
|
+
return { field: signalName, value: "[k \\in DOMAIN @ \\ {payload.key} |-> @[k]]" };
|
|
237215
|
+
}
|
|
237216
|
+
}
|
|
237001
237217
|
}
|
|
237002
237218
|
}
|
|
237219
|
+
return null;
|
|
237220
|
+
}
|
|
237221
|
+
extractArrayMethodOperation(callExpr, fieldPath, signalName) {
|
|
237222
|
+
const expression = callExpr.getExpression();
|
|
237223
|
+
if (!import_ts_morph4.Node.isPropertyAccessExpression(expression))
|
|
237224
|
+
return null;
|
|
237225
|
+
const methodName = expression.getName();
|
|
237226
|
+
const sourceExpr = expression.getExpression();
|
|
237227
|
+
const sourcePath = this.getPropertyPath(sourceExpr);
|
|
237228
|
+
if (sourcePath !== fieldPath)
|
|
237229
|
+
return null;
|
|
237230
|
+
switch (methodName) {
|
|
237231
|
+
case "filter":
|
|
237232
|
+
return { field: signalName, value: "SelectSeq(@, LAMBDA t: TRUE)" };
|
|
237233
|
+
case "map":
|
|
237234
|
+
return { field: signalName, value: "[i \\in DOMAIN @ |-> @[i]]" };
|
|
237235
|
+
case "slice":
|
|
237236
|
+
return { field: signalName, value: "SubSeq(@, 1, Len(@))" };
|
|
237237
|
+
case "concat":
|
|
237238
|
+
return { field: signalName, value: "@ \\o <<payload>>" };
|
|
237239
|
+
case "reverse":
|
|
237240
|
+
return { field: signalName, value: "[i \\in DOMAIN @ |-> @[Len(@) - i + 1]]" };
|
|
237241
|
+
default:
|
|
237242
|
+
this.warnUnsupportedArrayMethod(methodName, callExpr);
|
|
237243
|
+
return null;
|
|
237244
|
+
}
|
|
237245
|
+
}
|
|
237246
|
+
warnUnsupportedArrayMethod(methodName, node) {
|
|
237247
|
+
const mutatingMethods = [
|
|
237248
|
+
"push",
|
|
237249
|
+
"pop",
|
|
237250
|
+
"shift",
|
|
237251
|
+
"unshift",
|
|
237252
|
+
"splice",
|
|
237253
|
+
"sort",
|
|
237254
|
+
"fill",
|
|
237255
|
+
"copyWithin"
|
|
237256
|
+
];
|
|
237257
|
+
const queryMethods = [
|
|
237258
|
+
"find",
|
|
237259
|
+
"findIndex",
|
|
237260
|
+
"reduce",
|
|
237261
|
+
"reduceRight",
|
|
237262
|
+
"some",
|
|
237263
|
+
"every",
|
|
237264
|
+
"includes",
|
|
237265
|
+
"indexOf",
|
|
237266
|
+
"lastIndexOf"
|
|
237267
|
+
];
|
|
237268
|
+
const otherMethods = ["flat", "flatMap", "join", "toString", "toLocaleString"];
|
|
237269
|
+
if (mutatingMethods.includes(methodName)) {
|
|
237270
|
+
this.warnUnsupportedPattern(`array.${methodName}()`, this.getNodeLocation(node), `'${methodName}' mutates in place. Use spread syntax: [...arr, item] for append, arr.filter() for removal.`);
|
|
237271
|
+
} else if (queryMethods.includes(methodName)) {
|
|
237272
|
+
this.warnUnsupportedPattern(`array.${methodName}()`, this.getNodeLocation(node), `'${methodName}' returns a single value, not a new array. State assignment won't be extracted.`);
|
|
237273
|
+
} else if (otherMethods.includes(methodName)) {
|
|
237274
|
+
this.warnUnsupportedPattern(`array.${methodName}()`, this.getNodeLocation(node), `'${methodName}' is not supported for state extraction. Consider using map/filter instead.`);
|
|
237275
|
+
}
|
|
237276
|
+
}
|
|
237277
|
+
extractSpreadUpdateAssignments(objectLiteral, assignments, signalName) {
|
|
237278
|
+
for (const prop of objectLiteral.getProperties()) {
|
|
237279
|
+
if (import_ts_morph4.Node.isSpreadAssignment(prop))
|
|
237280
|
+
continue;
|
|
237281
|
+
this.extractPropertyAssignment(prop, assignments, signalName);
|
|
237282
|
+
}
|
|
237283
|
+
}
|
|
237284
|
+
extractArraySpreadOperation(arrayLiteral, fieldPath, signalName) {
|
|
237285
|
+
const elements = arrayLiteral.getElements();
|
|
237286
|
+
if (elements.length < 1)
|
|
237287
|
+
return null;
|
|
237288
|
+
return this.tryExtractAppendOperation(elements, fieldPath, signalName) ?? this.tryExtractPrependOperation(elements, fieldPath, signalName);
|
|
237289
|
+
}
|
|
237290
|
+
tryExtractAppendOperation(elements, fieldPath, signalName) {
|
|
237291
|
+
const firstElement = elements[0];
|
|
237292
|
+
if (!firstElement || !import_ts_morph4.Node.isSpreadElement(firstElement))
|
|
237293
|
+
return null;
|
|
237294
|
+
const spreadExpr = firstElement.getExpression();
|
|
237295
|
+
if (!spreadExpr || this.getPropertyPath(spreadExpr) !== fieldPath)
|
|
237296
|
+
return null;
|
|
237297
|
+
if (elements.length === 2) {
|
|
237298
|
+
return { field: signalName, value: "Append(@, payload)" };
|
|
237299
|
+
}
|
|
237300
|
+
const placeholders = Array(elements.length - 1).fill("payload").join(", ");
|
|
237301
|
+
return { field: signalName, value: `@ \\o <<${placeholders}>>` };
|
|
237302
|
+
}
|
|
237303
|
+
tryExtractPrependOperation(elements, fieldPath, signalName) {
|
|
237304
|
+
if (elements.length < 2)
|
|
237305
|
+
return null;
|
|
237306
|
+
const lastElement = elements[elements.length - 1];
|
|
237307
|
+
if (!lastElement || !import_ts_morph4.Node.isSpreadElement(lastElement))
|
|
237308
|
+
return null;
|
|
237309
|
+
const spreadExpr = lastElement.getExpression();
|
|
237310
|
+
if (!spreadExpr || this.getPropertyPath(spreadExpr) !== fieldPath)
|
|
237311
|
+
return null;
|
|
237312
|
+
if (elements.length === 2) {
|
|
237313
|
+
return { field: signalName, value: "<<payload>> \\o @" };
|
|
237314
|
+
}
|
|
237315
|
+
const placeholders = Array(elements.length - 1).fill("payload").join(", ");
|
|
237316
|
+
return { field: signalName, value: `<<${placeholders}>> \\o @` };
|
|
237317
|
+
}
|
|
237318
|
+
extractObjectLiteralAssignments(objectLiteral, assignments, signalName) {
|
|
237319
|
+
if (!import_ts_morph4.Node.isObjectLiteralExpression(objectLiteral))
|
|
237320
|
+
return;
|
|
237321
|
+
for (const prop of objectLiteral.getProperties()) {
|
|
237322
|
+
this.extractPropertyAssignment(prop, assignments, signalName);
|
|
237323
|
+
}
|
|
237324
|
+
}
|
|
237325
|
+
extractPropertyAssignment(prop, assignments, signalName) {
|
|
237326
|
+
if (import_ts_morph4.Node.isPropertyAssignment(prop)) {
|
|
237327
|
+
const name = prop.getName();
|
|
237328
|
+
const initializer = prop.getInitializer();
|
|
237329
|
+
if (!name || !initializer)
|
|
237330
|
+
return;
|
|
237331
|
+
const value = this.extractValue(initializer);
|
|
237332
|
+
if (value === undefined)
|
|
237333
|
+
return;
|
|
237334
|
+
const field = signalName ? `${signalName}_${name}` : name;
|
|
237335
|
+
assignments.push({ field, value });
|
|
237336
|
+
return;
|
|
237337
|
+
}
|
|
237338
|
+
if (import_ts_morph4.Node.isShorthandPropertyAssignment(prop)) {
|
|
237339
|
+
const name = prop.getName();
|
|
237340
|
+
const field = signalName ? `${signalName}_${name}` : name;
|
|
237341
|
+
assignments.push({ field, value: "@" });
|
|
237342
|
+
}
|
|
237003
237343
|
}
|
|
237004
237344
|
extractElementAccessAssignment(left, right, assignments) {
|
|
237005
237345
|
if (!import_ts_morph4.Node.isElementAccessExpression(left))
|
|
@@ -238012,15 +238352,15 @@ class HandlerExtractor {
|
|
|
238012
238352
|
if (path === `${varName}.value`) {
|
|
238013
238353
|
const right = node.getRight();
|
|
238014
238354
|
if (import_ts_morph4.Node.isObjectLiteralExpression(right)) {
|
|
238015
|
-
this.extractObjectLiteralAssignments(right, mutations);
|
|
238355
|
+
this.extractObjectLiteralAssignments(right, mutations, varName);
|
|
238016
238356
|
}
|
|
238017
238357
|
break;
|
|
238018
238358
|
}
|
|
238019
238359
|
const fieldPrefix = `${varName}.value.`;
|
|
238020
238360
|
if (path.startsWith(fieldPrefix)) {
|
|
238021
|
-
const
|
|
238361
|
+
const fieldName = path.substring(fieldPrefix.length);
|
|
238022
238362
|
const value = this.extractValue(node.getRight());
|
|
238023
|
-
mutations.push({ field
|
|
238363
|
+
mutations.push({ field: `${varName}_${fieldName}`, value: value ?? "@" });
|
|
238024
238364
|
break;
|
|
238025
238365
|
}
|
|
238026
238366
|
}
|
|
@@ -241019,4 +241359,4 @@ export {
|
|
|
241019
241359
|
generateTeachingMaterial
|
|
241020
241360
|
};
|
|
241021
241361
|
|
|
241022
|
-
//# debugId=
|
|
241362
|
+
//# debugId=5D30A66A660B187164756E2164756E21
|