@fairfox/polly 0.3.0 → 0.3.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.
|
@@ -727,10 +727,12 @@ import { Project, SyntaxKind, Node } from "ts-morph";
|
|
|
727
727
|
|
|
728
728
|
class HandlerExtractor {
|
|
729
729
|
project;
|
|
730
|
+
typeGuardCache;
|
|
730
731
|
constructor(tsConfigPath) {
|
|
731
732
|
this.project = new Project({
|
|
732
733
|
tsConfigFilePath: tsConfigPath
|
|
733
734
|
});
|
|
735
|
+
this.typeGuardCache = new WeakMap;
|
|
734
736
|
}
|
|
735
737
|
extractHandlers() {
|
|
736
738
|
const handlers = [];
|
|
@@ -773,6 +775,10 @@ class HandlerExtractor {
|
|
|
773
775
|
const mapHandlers = this.extractHandlerMapPattern(node, context, filePath);
|
|
774
776
|
handlers.push(...mapHandlers);
|
|
775
777
|
}
|
|
778
|
+
if (Node.isIfStatement(node)) {
|
|
779
|
+
const typeGuardHandlers = this.extractTypeGuardHandlers(node, context, filePath);
|
|
780
|
+
handlers.push(...typeGuardHandlers);
|
|
781
|
+
}
|
|
776
782
|
});
|
|
777
783
|
return handlers;
|
|
778
784
|
}
|
|
@@ -983,6 +989,113 @@ class HandlerExtractor {
|
|
|
983
989
|
} catch (error) {}
|
|
984
990
|
return handlers;
|
|
985
991
|
}
|
|
992
|
+
extractTypeGuardHandlers(ifNode, context, filePath) {
|
|
993
|
+
const handlers = [];
|
|
994
|
+
try {
|
|
995
|
+
const sourceFile = ifNode.getSourceFile();
|
|
996
|
+
let typeGuards = this.typeGuardCache.get(sourceFile);
|
|
997
|
+
if (!typeGuards) {
|
|
998
|
+
typeGuards = this.findTypePredicateFunctions(sourceFile);
|
|
999
|
+
this.typeGuardCache.set(sourceFile, typeGuards);
|
|
1000
|
+
}
|
|
1001
|
+
if (typeGuards.size === 0) {
|
|
1002
|
+
return handlers;
|
|
1003
|
+
}
|
|
1004
|
+
let currentIf = ifNode;
|
|
1005
|
+
while (currentIf) {
|
|
1006
|
+
const handler = this.extractHandlerFromIfClause(currentIf, typeGuards, context, filePath);
|
|
1007
|
+
if (handler) {
|
|
1008
|
+
handlers.push(handler);
|
|
1009
|
+
}
|
|
1010
|
+
const elseStatement = currentIf.getElseStatement();
|
|
1011
|
+
if (elseStatement && Node.isIfStatement(elseStatement)) {
|
|
1012
|
+
currentIf = elseStatement;
|
|
1013
|
+
} else {
|
|
1014
|
+
break;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
} catch (error) {}
|
|
1018
|
+
return handlers;
|
|
1019
|
+
}
|
|
1020
|
+
extractHandlerFromIfClause(ifNode, typeGuards, context, filePath) {
|
|
1021
|
+
try {
|
|
1022
|
+
const condition = ifNode.getExpression();
|
|
1023
|
+
if (!Node.isCallExpression(condition)) {
|
|
1024
|
+
return null;
|
|
1025
|
+
}
|
|
1026
|
+
const funcExpr = condition.getExpression();
|
|
1027
|
+
let funcName;
|
|
1028
|
+
if (Node.isIdentifier(funcExpr)) {
|
|
1029
|
+
funcName = funcExpr.getText();
|
|
1030
|
+
}
|
|
1031
|
+
if (!funcName || !typeGuards.has(funcName)) {
|
|
1032
|
+
return null;
|
|
1033
|
+
}
|
|
1034
|
+
const messageType = typeGuards.get(funcName);
|
|
1035
|
+
const line = ifNode.getStartLineNumber();
|
|
1036
|
+
return {
|
|
1037
|
+
messageType,
|
|
1038
|
+
node: context,
|
|
1039
|
+
assignments: [],
|
|
1040
|
+
preconditions: [],
|
|
1041
|
+
postconditions: [],
|
|
1042
|
+
location: { file: filePath, line }
|
|
1043
|
+
};
|
|
1044
|
+
} catch (error) {
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
findTypePredicateFunctions(sourceFile) {
|
|
1049
|
+
const typeGuards = new Map;
|
|
1050
|
+
sourceFile.forEachDescendant((node) => {
|
|
1051
|
+
if (Node.isFunctionDeclaration(node) || Node.isFunctionExpression(node) || Node.isArrowFunction(node)) {
|
|
1052
|
+
const returnType = node.getReturnType();
|
|
1053
|
+
const returnTypeText = returnType.getText();
|
|
1054
|
+
if (/is\s+\w+/.test(returnTypeText)) {
|
|
1055
|
+
let functionName;
|
|
1056
|
+
if (Node.isFunctionDeclaration(node)) {
|
|
1057
|
+
functionName = node.getName();
|
|
1058
|
+
} else if (Node.isFunctionExpression(node)) {
|
|
1059
|
+
const parent = node.getParent();
|
|
1060
|
+
if (Node.isVariableDeclaration(parent)) {
|
|
1061
|
+
functionName = parent.getName();
|
|
1062
|
+
}
|
|
1063
|
+
} else if (Node.isArrowFunction(node)) {
|
|
1064
|
+
const parent = node.getParent();
|
|
1065
|
+
if (Node.isVariableDeclaration(parent)) {
|
|
1066
|
+
functionName = parent.getName();
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
if (functionName) {
|
|
1070
|
+
let messageType = null;
|
|
1071
|
+
const typeMatch = returnTypeText.match(/is\s+(\w+)/);
|
|
1072
|
+
if (typeMatch) {
|
|
1073
|
+
const typeName = typeMatch[1];
|
|
1074
|
+
messageType = this.extractMessageTypeFromTypeName(typeName);
|
|
1075
|
+
}
|
|
1076
|
+
if (!messageType) {
|
|
1077
|
+
const body = node.getBody();
|
|
1078
|
+
if (body) {
|
|
1079
|
+
const bodyText = body.getText();
|
|
1080
|
+
const typeValueMatch = bodyText.match(/\.type\s*===?\s*['"](\w+)['"]/);
|
|
1081
|
+
if (typeValueMatch) {
|
|
1082
|
+
messageType = typeValueMatch[1];
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
if (messageType) {
|
|
1087
|
+
typeGuards.set(functionName, messageType);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
return typeGuards;
|
|
1094
|
+
}
|
|
1095
|
+
extractMessageTypeFromTypeName(typeName) {
|
|
1096
|
+
const messageType = typeName.replace(/Message$/, "").replace(/Event$/, "").replace(/Request$/, "").replace(/Command$/, "").replace(/Query$/, "").toLowerCase();
|
|
1097
|
+
return messageType;
|
|
1098
|
+
}
|
|
986
1099
|
inferContext(filePath) {
|
|
987
1100
|
const path = filePath.toLowerCase();
|
|
988
1101
|
if (path.includes("/background/") || path.includes("\\background\\")) {
|
|
@@ -2175,4 +2288,4 @@ Stack trace:`, COLORS.gray));
|
|
|
2175
2288
|
process.exit(1);
|
|
2176
2289
|
});
|
|
2177
2290
|
|
|
2178
|
-
//# debugId=
|
|
2291
|
+
//# debugId=5E943FE5FB56B58764756E2164756E21
|