@suss/adapter-typescript 0.22.2 → 0.22.3
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/index.cjs +270 -247
- package/dist/index.js +266 -243
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -4647,6 +4647,26 @@ function resolveImportedLocalName(sourceFile, importModule, importName) {
|
|
|
4647
4647
|
}
|
|
4648
4648
|
return null;
|
|
4649
4649
|
}
|
|
4650
|
+
function importedReferenceSpellings(sourceFile, importModule, importName) {
|
|
4651
|
+
const spellings = [];
|
|
4652
|
+
const localName = resolveImportedLocalName(
|
|
4653
|
+
sourceFile,
|
|
4654
|
+
importModule,
|
|
4655
|
+
importName
|
|
4656
|
+
);
|
|
4657
|
+
if (localName !== null) {
|
|
4658
|
+
spellings.push(localName);
|
|
4659
|
+
}
|
|
4660
|
+
if (!sourceFile.getFullText().includes(`.${importName}`)) {
|
|
4661
|
+
return spellings;
|
|
4662
|
+
}
|
|
4663
|
+
for (const root of importedRootsOf(sourceFile, [importModule])) {
|
|
4664
|
+
if (root !== importName) {
|
|
4665
|
+
spellings.push(`${root}.${importName}`);
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
return spellings;
|
|
4669
|
+
}
|
|
4650
4670
|
|
|
4651
4671
|
// src/discovery/resolveValue.ts
|
|
4652
4672
|
import { Node as Node17 } from "ts-morph";
|
|
@@ -8093,13 +8113,13 @@ function collectMethodsCalledOnCallResults(sourceFile) {
|
|
|
8093
8113
|
return called;
|
|
8094
8114
|
}
|
|
8095
8115
|
function registrationSubjectsOf(sourceFile, importModule, importName, resolution) {
|
|
8096
|
-
const
|
|
8116
|
+
const spellings = importedReferenceSpellings(
|
|
8097
8117
|
sourceFile,
|
|
8098
8118
|
importModule,
|
|
8099
8119
|
importName
|
|
8100
8120
|
);
|
|
8101
8121
|
const subjects = /* @__PURE__ */ new Map();
|
|
8102
|
-
if (
|
|
8122
|
+
if (spellings.length === 0) {
|
|
8103
8123
|
return subjects;
|
|
8104
8124
|
}
|
|
8105
8125
|
sourceFile.forEachDescendant((node) => {
|
|
@@ -8109,7 +8129,7 @@ function registrationSubjectsOf(sourceFile, importModule, importName, resolution
|
|
|
8109
8129
|
return;
|
|
8110
8130
|
}
|
|
8111
8131
|
const calleeText = Node32.isCallExpression(init) || Node32.isNewExpression(init) ? init.getExpression().getText() : null;
|
|
8112
|
-
if (calleeText
|
|
8132
|
+
if (calleeText !== null && spellings.includes(calleeText)) {
|
|
8113
8133
|
subjects.set(node.getName(), init);
|
|
8114
8134
|
}
|
|
8115
8135
|
return;
|
|
@@ -8122,7 +8142,9 @@ function registrationSubjectsOf(sourceFile, importModule, importName, resolution
|
|
|
8122
8142
|
return;
|
|
8123
8143
|
}
|
|
8124
8144
|
const typeText = typeNode.getText();
|
|
8125
|
-
if (
|
|
8145
|
+
if (spellings.some(
|
|
8146
|
+
(spelling) => typeText === spelling || typeText.startsWith(`${spelling}<`)
|
|
8147
|
+
)) {
|
|
8126
8148
|
subjects.set(node.getName(), creationSiteBehind(node, resolution));
|
|
8127
8149
|
}
|
|
8128
8150
|
});
|
|
@@ -8166,17 +8188,17 @@ function registrationSubjectIdsOf(sourceFile, matches, resolution) {
|
|
|
8166
8188
|
return ids;
|
|
8167
8189
|
}
|
|
8168
8190
|
function unboundConstructionsOf(sourceFile, importModule, importName) {
|
|
8169
|
-
const
|
|
8191
|
+
const spellings = importedReferenceSpellings(
|
|
8170
8192
|
sourceFile,
|
|
8171
8193
|
importModule,
|
|
8172
8194
|
importName
|
|
8173
8195
|
);
|
|
8174
|
-
if (
|
|
8196
|
+
if (spellings.length === 0) {
|
|
8175
8197
|
return [];
|
|
8176
8198
|
}
|
|
8177
8199
|
const constructions = [];
|
|
8178
8200
|
sourceFile.forEachDescendant((node) => {
|
|
8179
|
-
if ((Node32.isCallExpression(node) || Node32.isNewExpression(node)) && node.getExpression().getText()
|
|
8201
|
+
if ((Node32.isCallExpression(node) || Node32.isNewExpression(node)) && spellings.includes(node.getExpression().getText()) && !Node32.isVariableDeclaration(node.getParent())) {
|
|
8180
8202
|
constructions.push(node);
|
|
8181
8203
|
}
|
|
8182
8204
|
});
|
|
@@ -10213,202 +10235,15 @@ function tryMatchParameterCall(node, func, pattern, match) {
|
|
|
10213
10235
|
return { node, terminal };
|
|
10214
10236
|
}
|
|
10215
10237
|
|
|
10216
|
-
// src/terminals/
|
|
10217
|
-
import { Node as Node44 } from "ts-morph";
|
|
10218
|
-
function tryMatchJsxReturn(node, pattern) {
|
|
10219
|
-
let expr;
|
|
10220
|
-
let source;
|
|
10221
|
-
if (Node44.isReturnStatement(node)) {
|
|
10222
|
-
expr = node.getExpression();
|
|
10223
|
-
source = node;
|
|
10224
|
-
} else if (Node44.isArrowFunction(node)) {
|
|
10225
|
-
const body = node.getBody();
|
|
10226
|
-
if (body !== void 0 && !Node44.isBlock(body)) {
|
|
10227
|
-
expr = body;
|
|
10228
|
-
source = body;
|
|
10229
|
-
}
|
|
10230
|
-
}
|
|
10231
|
-
if (expr === void 0 || source === void 0) {
|
|
10232
|
-
return null;
|
|
10233
|
-
}
|
|
10234
|
-
const tree = jsxToRenderNode(expr);
|
|
10235
|
-
if (tree === null) {
|
|
10236
|
-
return null;
|
|
10237
|
-
}
|
|
10238
|
-
const component = tree.type === "element" ? tree.tag : "Fragment";
|
|
10239
|
-
const terminal = {
|
|
10240
|
-
kind: pattern.kind,
|
|
10241
|
-
statusCode: null,
|
|
10242
|
-
body: null,
|
|
10243
|
-
exceptionType: null,
|
|
10244
|
-
message: null,
|
|
10245
|
-
component,
|
|
10246
|
-
delegateTarget: null,
|
|
10247
|
-
emitEvent: null,
|
|
10248
|
-
renderTree: tree,
|
|
10249
|
-
location: {
|
|
10250
|
-
start: startLineOf(node),
|
|
10251
|
-
end: endLineOf(node)
|
|
10252
|
-
}
|
|
10253
|
-
};
|
|
10254
|
-
return { node, source, terminal };
|
|
10255
|
-
}
|
|
10256
|
-
function componentTargetOf(tagNode) {
|
|
10257
|
-
if (!Node44.isIdentifier(tagNode) || !/^[A-Z]/.test(tagNode.getText())) {
|
|
10258
|
-
return null;
|
|
10259
|
-
}
|
|
10260
|
-
const target = functionTargetOf(tagNode);
|
|
10261
|
-
return target === null ? null : { file: target.file, name: target.name };
|
|
10262
|
-
}
|
|
10263
|
-
function jsxToRenderNode(node) {
|
|
10264
|
-
if (Node44.isJsxElement(node)) {
|
|
10265
|
-
const opening = node.getOpeningElement();
|
|
10266
|
-
const tag = opening.getTagNameNode().getText();
|
|
10267
|
-
const attrs = collectJsxAttributes(opening);
|
|
10268
|
-
const target = componentTargetOf(opening.getTagNameNode());
|
|
10269
|
-
const children = node.getJsxChildren().map(jsxChildToRenderNode).filter((n) => n !== null);
|
|
10270
|
-
return {
|
|
10271
|
-
type: "element",
|
|
10272
|
-
tag,
|
|
10273
|
-
children,
|
|
10274
|
-
...attrs !== null ? { attrs } : {},
|
|
10275
|
-
...target !== null ? { target } : {}
|
|
10276
|
-
};
|
|
10277
|
-
}
|
|
10278
|
-
if (Node44.isJsxSelfClosingElement(node)) {
|
|
10279
|
-
const tag = node.getTagNameNode().getText();
|
|
10280
|
-
const attrs = collectJsxAttributes(node);
|
|
10281
|
-
const target = componentTargetOf(node.getTagNameNode());
|
|
10282
|
-
return {
|
|
10283
|
-
type: "element",
|
|
10284
|
-
tag,
|
|
10285
|
-
children: [],
|
|
10286
|
-
...attrs !== null ? { attrs } : {},
|
|
10287
|
-
...target !== null ? { target } : {}
|
|
10288
|
-
};
|
|
10289
|
-
}
|
|
10290
|
-
if (Node44.isJsxFragment(node)) {
|
|
10291
|
-
const children = node.getJsxChildren().map(jsxChildToRenderNode).filter((n) => n !== null);
|
|
10292
|
-
return { type: "element", tag: "Fragment", children };
|
|
10293
|
-
}
|
|
10294
|
-
if (Node44.isParenthesizedExpression(node)) {
|
|
10295
|
-
return jsxToRenderNode(node.getExpression());
|
|
10296
|
-
}
|
|
10297
|
-
return null;
|
|
10298
|
-
}
|
|
10299
|
-
function collectJsxAttributes(opening) {
|
|
10300
|
-
const entries = {};
|
|
10301
|
-
for (const attr of opening.getAttributes()) {
|
|
10302
|
-
if (Node44.isJsxSpreadAttribute(attr)) {
|
|
10303
|
-
const exprText = attr.getExpression().getText();
|
|
10304
|
-
entries[`...${exprText}`] = exprText;
|
|
10305
|
-
continue;
|
|
10306
|
-
}
|
|
10307
|
-
if (!Node44.isJsxAttribute(attr)) {
|
|
10308
|
-
continue;
|
|
10309
|
-
}
|
|
10310
|
-
const name = attr.getNameNode().getText();
|
|
10311
|
-
const initializer = attr.getInitializer();
|
|
10312
|
-
if (initializer === void 0) {
|
|
10313
|
-
entries[name] = "";
|
|
10314
|
-
continue;
|
|
10315
|
-
}
|
|
10316
|
-
if (Node44.isJsxExpression(initializer)) {
|
|
10317
|
-
const inner = initializer.getExpression();
|
|
10318
|
-
entries[name] = inner !== void 0 ? inner.getText() : "";
|
|
10319
|
-
continue;
|
|
10320
|
-
}
|
|
10321
|
-
entries[name] = initializer.getText();
|
|
10322
|
-
}
|
|
10323
|
-
return Object.keys(entries).length > 0 ? entries : null;
|
|
10324
|
-
}
|
|
10325
|
-
function jsxChildToRenderNode(child) {
|
|
10326
|
-
if (Node44.isJsxText(child)) {
|
|
10327
|
-
const text = child.getLiteralText().trim();
|
|
10328
|
-
if (text.length === 0) {
|
|
10329
|
-
return null;
|
|
10330
|
-
}
|
|
10331
|
-
return { type: "text", value: text };
|
|
10332
|
-
}
|
|
10333
|
-
if (Node44.isJsxExpression(child)) {
|
|
10334
|
-
const inner = child.getExpression();
|
|
10335
|
-
if (inner === void 0) {
|
|
10336
|
-
return null;
|
|
10337
|
-
}
|
|
10338
|
-
return jsxExpressionToRenderNode(inner);
|
|
10339
|
-
}
|
|
10340
|
-
if (Node44.isJsxElement(child) || Node44.isJsxSelfClosingElement(child) || Node44.isJsxFragment(child)) {
|
|
10341
|
-
return jsxToRenderNode(child);
|
|
10342
|
-
}
|
|
10343
|
-
return null;
|
|
10344
|
-
}
|
|
10345
|
-
function jsxExpressionToRenderNode(expr) {
|
|
10346
|
-
if (Node44.isParenthesizedExpression(expr)) {
|
|
10347
|
-
return jsxExpressionToRenderNode(expr.getExpression());
|
|
10348
|
-
}
|
|
10349
|
-
if (Node44.isBinaryExpression(expr)) {
|
|
10350
|
-
const op = expr.getOperatorToken().getText();
|
|
10351
|
-
if (op === "&&") {
|
|
10352
|
-
const right = renderAlternative(peelParens(expr.getRight()));
|
|
10353
|
-
if (right.kind === "jsx") {
|
|
10354
|
-
return {
|
|
10355
|
-
type: "conditional",
|
|
10356
|
-
condition: expr.getLeft().getText(),
|
|
10357
|
-
whenTrue: right.node,
|
|
10358
|
-
whenFalse: null
|
|
10359
|
-
};
|
|
10360
|
-
}
|
|
10361
|
-
}
|
|
10362
|
-
}
|
|
10363
|
-
if (Node44.isConditionalExpression(expr)) {
|
|
10364
|
-
const truthy = renderAlternative(peelParens(expr.getWhenTrue()));
|
|
10365
|
-
const falsy = renderAlternative(peelParens(expr.getWhenFalse()));
|
|
10366
|
-
if (truthy.kind === "jsx") {
|
|
10367
|
-
return {
|
|
10368
|
-
type: "conditional",
|
|
10369
|
-
condition: expr.getCondition().getText(),
|
|
10370
|
-
whenTrue: truthy.node,
|
|
10371
|
-
whenFalse: falsy.kind === "jsx" ? falsy.node : null
|
|
10372
|
-
};
|
|
10373
|
-
}
|
|
10374
|
-
if (falsy.kind === "jsx") {
|
|
10375
|
-
return {
|
|
10376
|
-
type: "conditional",
|
|
10377
|
-
condition: `!(${expr.getCondition().getText()})`,
|
|
10378
|
-
whenTrue: falsy.node,
|
|
10379
|
-
whenFalse: null
|
|
10380
|
-
};
|
|
10381
|
-
}
|
|
10382
|
-
}
|
|
10383
|
-
return { type: "expression", sourceText: expr.getText() };
|
|
10384
|
-
}
|
|
10385
|
-
function renderAlternative(node) {
|
|
10386
|
-
if (Node44.isNullLiteral(node)) {
|
|
10387
|
-
return { kind: "noRender" };
|
|
10388
|
-
}
|
|
10389
|
-
if (Node44.isFalseLiteral(node)) {
|
|
10390
|
-
return { kind: "noRender" };
|
|
10391
|
-
}
|
|
10392
|
-
if (Node44.isIdentifier(node) && node.getText() === "undefined") {
|
|
10393
|
-
return { kind: "noRender" };
|
|
10394
|
-
}
|
|
10395
|
-
if (Node44.isJsxElement(node) || Node44.isJsxSelfClosingElement(node) || Node44.isJsxFragment(node)) {
|
|
10396
|
-
const tree = jsxToRenderNode(node);
|
|
10397
|
-
if (tree !== null) {
|
|
10398
|
-
return { kind: "jsx", node: tree };
|
|
10399
|
-
}
|
|
10400
|
-
}
|
|
10401
|
-
return { kind: "notStatic" };
|
|
10402
|
-
}
|
|
10403
|
-
|
|
10404
|
-
// src/terminals/returns.ts
|
|
10238
|
+
// src/terminals/extract.ts
|
|
10405
10239
|
import {
|
|
10406
|
-
Node as
|
|
10240
|
+
Node as Node45
|
|
10407
10241
|
} from "ts-morph";
|
|
10242
|
+
import { constantOf } from "@suss/values";
|
|
10408
10243
|
|
|
10409
10244
|
// src/shapes/shapes.ts
|
|
10410
10245
|
import {
|
|
10411
|
-
Node as
|
|
10246
|
+
Node as Node44,
|
|
10412
10247
|
SyntaxKind as SyntaxKind10
|
|
10413
10248
|
} from "ts-morph";
|
|
10414
10249
|
|
|
@@ -10869,35 +10704,35 @@ function extractShapeWithArguments(node, substitutions) {
|
|
|
10869
10704
|
}
|
|
10870
10705
|
function extractShapeInner(node) {
|
|
10871
10706
|
const unwrapped2 = peelSyntax(node);
|
|
10872
|
-
if (boundArguments !== null &&
|
|
10707
|
+
if (boundArguments !== null && Node44.isIdentifier(unwrapped2)) {
|
|
10873
10708
|
const argument = boundArguments.get(unwrapped2.getText());
|
|
10874
10709
|
if (argument !== void 0 && argument !== unwrapped2) {
|
|
10875
10710
|
return extractShape(argument);
|
|
10876
10711
|
}
|
|
10877
10712
|
}
|
|
10878
|
-
if (
|
|
10713
|
+
if (Node44.isObjectLiteralExpression(unwrapped2)) {
|
|
10879
10714
|
return shapeFromObjectLiteral(unwrapped2);
|
|
10880
10715
|
}
|
|
10881
|
-
if (
|
|
10716
|
+
if (Node44.isArrayLiteralExpression(unwrapped2)) {
|
|
10882
10717
|
return shapeFromArrayLiteral(unwrapped2);
|
|
10883
10718
|
}
|
|
10884
|
-
if (
|
|
10719
|
+
if (Node44.isStringLiteral(unwrapped2) || Node44.isNoSubstitutionTemplateLiteral(unwrapped2)) {
|
|
10885
10720
|
return { type: "literal", value: unwrapped2.getLiteralValue() };
|
|
10886
10721
|
}
|
|
10887
|
-
if (
|
|
10722
|
+
if (Node44.isTemplateExpression(unwrapped2)) {
|
|
10888
10723
|
return { type: "text" };
|
|
10889
10724
|
}
|
|
10890
|
-
if (
|
|
10725
|
+
if (Node44.isNumericLiteral(unwrapped2)) {
|
|
10891
10726
|
return numericLiteralShape(
|
|
10892
10727
|
unwrapped2.getLiteralValue(),
|
|
10893
10728
|
unwrapped2.getText()
|
|
10894
10729
|
);
|
|
10895
10730
|
}
|
|
10896
|
-
if (
|
|
10731
|
+
if (Node44.isPrefixUnaryExpression(unwrapped2)) {
|
|
10897
10732
|
const op = unwrapped2.getOperatorToken();
|
|
10898
10733
|
if (op === SyntaxKind10.MinusToken || op === SyntaxKind10.PlusToken) {
|
|
10899
10734
|
const inner = unwrapped2.getOperand();
|
|
10900
|
-
if (
|
|
10735
|
+
if (Node44.isNumericLiteral(inner)) {
|
|
10901
10736
|
const v3 = inner.getLiteralValue();
|
|
10902
10737
|
const signed = op === SyntaxKind10.MinusToken ? -v3 : v3;
|
|
10903
10738
|
const rawBody = inner.getText();
|
|
@@ -10906,7 +10741,7 @@ function extractShapeInner(node) {
|
|
|
10906
10741
|
}
|
|
10907
10742
|
}
|
|
10908
10743
|
}
|
|
10909
|
-
if (
|
|
10744
|
+
if (Node44.isBigIntLiteral(unwrapped2)) {
|
|
10910
10745
|
return { type: "ref", name: "bigint" };
|
|
10911
10746
|
}
|
|
10912
10747
|
const kind = unwrapped2.getKind();
|
|
@@ -10919,10 +10754,10 @@ function extractShapeInner(node) {
|
|
|
10919
10754
|
if (kind === SyntaxKind10.NullKeyword) {
|
|
10920
10755
|
return { type: "null" };
|
|
10921
10756
|
}
|
|
10922
|
-
if (
|
|
10757
|
+
if (Node44.isIdentifier(unwrapped2) && unwrapped2.getText() === "undefined") {
|
|
10923
10758
|
return { type: "undefined" };
|
|
10924
10759
|
}
|
|
10925
|
-
if (
|
|
10760
|
+
if (Node44.isConditionalExpression(unwrapped2)) {
|
|
10926
10761
|
const whenTrue = extractShape(unwrapped2.getWhenTrue());
|
|
10927
10762
|
const whenFalse = extractShape(unwrapped2.getWhenFalse());
|
|
10928
10763
|
const variants = [];
|
|
@@ -10953,7 +10788,7 @@ function shapeFromArrayLiteral(arr) {
|
|
|
10953
10788
|
}
|
|
10954
10789
|
const shapes = [];
|
|
10955
10790
|
for (const el of elements) {
|
|
10956
|
-
if (
|
|
10791
|
+
if (Node44.isSpreadElement(el)) {
|
|
10957
10792
|
const inner = el.getExpression();
|
|
10958
10793
|
const innerShape = extractShape(inner);
|
|
10959
10794
|
if (innerShape?.type === "array") {
|
|
@@ -10972,7 +10807,7 @@ function shapeFromObjectLiteral(obj) {
|
|
|
10972
10807
|
const properties = {};
|
|
10973
10808
|
const unresolvedSpreads = [];
|
|
10974
10809
|
for (const prop of obj.getProperties()) {
|
|
10975
|
-
if (
|
|
10810
|
+
if (Node44.isPropertyAssignment(prop)) {
|
|
10976
10811
|
const name = propertyName2(prop);
|
|
10977
10812
|
if (name === null) {
|
|
10978
10813
|
continue;
|
|
@@ -10988,7 +10823,7 @@ function shapeFromObjectLiteral(obj) {
|
|
|
10988
10823
|
};
|
|
10989
10824
|
continue;
|
|
10990
10825
|
}
|
|
10991
|
-
if (
|
|
10826
|
+
if (Node44.isShorthandPropertyAssignment(prop)) {
|
|
10992
10827
|
const name = prop.getName();
|
|
10993
10828
|
const valueExpr = prop.getNameNode();
|
|
10994
10829
|
properties[name] = extractShape(valueExpr) ?? {
|
|
@@ -10997,7 +10832,7 @@ function shapeFromObjectLiteral(obj) {
|
|
|
10997
10832
|
};
|
|
10998
10833
|
continue;
|
|
10999
10834
|
}
|
|
11000
|
-
if (
|
|
10835
|
+
if (Node44.isSpreadAssignment(prop)) {
|
|
11001
10836
|
const expr = prop.getExpression();
|
|
11002
10837
|
const spreadShape = extractShape(expr);
|
|
11003
10838
|
if (spreadShape?.type === "record") {
|
|
@@ -11016,7 +10851,7 @@ function shapeFromObjectLiteral(obj) {
|
|
|
11016
10851
|
}
|
|
11017
10852
|
function propertyName2(prop) {
|
|
11018
10853
|
const nameNode = prop.getNameNode();
|
|
11019
|
-
if (
|
|
10854
|
+
if (Node44.isIdentifier(nameNode) || Node44.isStringLiteral(nameNode) || Node44.isNoSubstitutionTemplateLiteral(nameNode) || Node44.isNumericLiteral(nameNode)) {
|
|
11020
10855
|
return nameNode.getText().replace(/^["']|["']$/g, "");
|
|
11021
10856
|
}
|
|
11022
10857
|
return null;
|
|
@@ -11042,24 +10877,20 @@ function collapseVariants2(shapes) {
|
|
|
11042
10877
|
}
|
|
11043
10878
|
|
|
11044
10879
|
// src/terminals/extract.ts
|
|
11045
|
-
import {
|
|
11046
|
-
Node as Node46
|
|
11047
|
-
} from "ts-morph";
|
|
11048
|
-
import { constantOf } from "@suss/values";
|
|
11049
10880
|
function unwrapAs(node) {
|
|
11050
10881
|
return peelSyntax(node);
|
|
11051
10882
|
}
|
|
11052
10883
|
function unwrapJsonStringify(node) {
|
|
11053
10884
|
const outer = unwrapAs(node);
|
|
11054
|
-
if (!
|
|
10885
|
+
if (!Node45.isCallExpression(outer)) {
|
|
11055
10886
|
return node;
|
|
11056
10887
|
}
|
|
11057
10888
|
const callee = outer.getExpression();
|
|
11058
|
-
if (!
|
|
10889
|
+
if (!Node45.isPropertyAccessExpression(callee) || callee.getName() !== "stringify") {
|
|
11059
10890
|
return node;
|
|
11060
10891
|
}
|
|
11061
10892
|
const receiver = callee.getExpression();
|
|
11062
|
-
if (!
|
|
10893
|
+
if (!Node45.isIdentifier(receiver) || receiver.getText() !== "JSON") {
|
|
11063
10894
|
return node;
|
|
11064
10895
|
}
|
|
11065
10896
|
const args = outer.getArguments();
|
|
@@ -11069,7 +10900,7 @@ function unwrapJsonStringify(node) {
|
|
|
11069
10900
|
return unwrapAs(args[0]);
|
|
11070
10901
|
}
|
|
11071
10902
|
function substituted(value, ctx) {
|
|
11072
|
-
if (ctx.substitutions === void 0 || !
|
|
10903
|
+
if (ctx.substitutions === void 0 || !Node45.isIdentifier(value)) {
|
|
11073
10904
|
return value;
|
|
11074
10905
|
}
|
|
11075
10906
|
return ctx.substitutions.get(value.getText()) ?? value;
|
|
@@ -11082,10 +10913,10 @@ function extractStatusCode(ctx) {
|
|
|
11082
10913
|
if (result !== null) {
|
|
11083
10914
|
return result;
|
|
11084
10915
|
}
|
|
11085
|
-
|
|
11086
|
-
|
|
11087
|
-
|
|
11088
|
-
return null;
|
|
10916
|
+
return declaredStatusCode(ctx.extraction);
|
|
10917
|
+
}
|
|
10918
|
+
function declaredStatusCode(extraction) {
|
|
10919
|
+
return extraction.defaultStatusCode !== void 0 ? { type: "literal", value: extraction.defaultStatusCode } : null;
|
|
11089
10920
|
}
|
|
11090
10921
|
function matchConstructorCode(ctorText, codes) {
|
|
11091
10922
|
const fullMatch = codes[ctorText];
|
|
@@ -11113,10 +10944,10 @@ function statusFromProperty(obj, name, ctx) {
|
|
|
11113
10944
|
if (prop === void 0) {
|
|
11114
10945
|
return null;
|
|
11115
10946
|
}
|
|
11116
|
-
if (
|
|
10947
|
+
if (Node45.isShorthandPropertyAssignment(prop)) {
|
|
11117
10948
|
return { type: "dynamic", sourceText: prop.getName() };
|
|
11118
10949
|
}
|
|
11119
|
-
if (!
|
|
10950
|
+
if (!Node45.isPropertyAssignment(prop)) {
|
|
11120
10951
|
return null;
|
|
11121
10952
|
}
|
|
11122
10953
|
const value = prop.getInitializer();
|
|
@@ -11139,7 +10970,7 @@ function extractStatusCodeFromRule(ctx) {
|
|
|
11139
10970
|
return null;
|
|
11140
10971
|
}
|
|
11141
10972
|
const first = ctx.throwCallArgs?.[0];
|
|
11142
|
-
if (first !== void 0 &&
|
|
10973
|
+
if (first !== void 0 && Node45.isNumericLiteral(first)) {
|
|
11143
10974
|
const value = first.getLiteralValue();
|
|
11144
10975
|
if (value >= 100 && value <= 599) {
|
|
11145
10976
|
return { type: "literal", value };
|
|
@@ -11152,7 +10983,7 @@ function extractStatusCodeFromRule(ctx) {
|
|
|
11152
10983
|
return null;
|
|
11153
10984
|
}
|
|
11154
10985
|
const arg = ctx.throwCallArgs[sc.position];
|
|
11155
|
-
if (arg === void 0 || !
|
|
10986
|
+
if (arg === void 0 || !Node45.isNewExpression(arg)) {
|
|
11156
10987
|
return null;
|
|
11157
10988
|
}
|
|
11158
10989
|
const ctorText = arg.getExpression().getText();
|
|
@@ -11161,7 +10992,7 @@ function extractStatusCodeFromRule(ctx) {
|
|
|
11161
10992
|
if (sc.from === "argumentProperty") {
|
|
11162
10993
|
const args = ctx.throwCallArgs ?? ctx.calls?.[0]?.getArguments();
|
|
11163
10994
|
const arg = args?.[sc.position];
|
|
11164
|
-
if (arg === void 0 || !
|
|
10995
|
+
if (arg === void 0 || !Node45.isObjectLiteralExpression(arg)) {
|
|
11165
10996
|
return null;
|
|
11166
10997
|
}
|
|
11167
10998
|
return statusFromProperty(arg, sc.name, ctx);
|
|
@@ -11171,8 +11002,8 @@ function extractStatusCodeFromRule(ctx) {
|
|
|
11171
11002
|
return null;
|
|
11172
11003
|
}
|
|
11173
11004
|
for (const prop of ctx.returnedObj.getProperties()) {
|
|
11174
|
-
if (!
|
|
11175
|
-
if (
|
|
11005
|
+
if (!Node45.isPropertyAssignment(prop)) {
|
|
11006
|
+
if (Node45.isShorthandPropertyAssignment(prop)) {
|
|
11176
11007
|
if (prop.getName() === sc.name) {
|
|
11177
11008
|
const resolved = ctx.substitutions?.get(prop.getName());
|
|
11178
11009
|
if (resolved !== void 0) {
|
|
@@ -11230,8 +11061,8 @@ function extractBody(ctx) {
|
|
|
11230
11061
|
return null;
|
|
11231
11062
|
}
|
|
11232
11063
|
for (const prop of ctx.returnedObj.getProperties()) {
|
|
11233
|
-
if (!
|
|
11234
|
-
if (
|
|
11064
|
+
if (!Node45.isPropertyAssignment(prop)) {
|
|
11065
|
+
if (Node45.isShorthandPropertyAssignment(prop)) {
|
|
11235
11066
|
if (prop.getName() === b.name) {
|
|
11236
11067
|
const resolved = ctx.substitutions?.get(prop.getName());
|
|
11237
11068
|
if (resolved !== void 0) {
|
|
@@ -11285,6 +11116,199 @@ function extractBody(ctx) {
|
|
|
11285
11116
|
return null;
|
|
11286
11117
|
}
|
|
11287
11118
|
|
|
11119
|
+
// src/terminals/jsx.ts
|
|
11120
|
+
import { Node as Node46 } from "ts-morph";
|
|
11121
|
+
function tryMatchJsxReturn(node, pattern) {
|
|
11122
|
+
let expr;
|
|
11123
|
+
let source;
|
|
11124
|
+
if (Node46.isReturnStatement(node)) {
|
|
11125
|
+
expr = node.getExpression();
|
|
11126
|
+
source = node;
|
|
11127
|
+
} else if (Node46.isArrowFunction(node)) {
|
|
11128
|
+
const body = node.getBody();
|
|
11129
|
+
if (body !== void 0 && !Node46.isBlock(body)) {
|
|
11130
|
+
expr = body;
|
|
11131
|
+
source = body;
|
|
11132
|
+
}
|
|
11133
|
+
}
|
|
11134
|
+
if (expr === void 0 || source === void 0) {
|
|
11135
|
+
return null;
|
|
11136
|
+
}
|
|
11137
|
+
const tree = jsxToRenderNode(expr);
|
|
11138
|
+
if (tree === null) {
|
|
11139
|
+
return null;
|
|
11140
|
+
}
|
|
11141
|
+
const component = tree.type === "element" ? tree.tag : "Fragment";
|
|
11142
|
+
const terminal = {
|
|
11143
|
+
kind: pattern.kind,
|
|
11144
|
+
statusCode: null,
|
|
11145
|
+
body: null,
|
|
11146
|
+
exceptionType: null,
|
|
11147
|
+
message: null,
|
|
11148
|
+
component,
|
|
11149
|
+
delegateTarget: null,
|
|
11150
|
+
emitEvent: null,
|
|
11151
|
+
renderTree: tree,
|
|
11152
|
+
location: {
|
|
11153
|
+
start: startLineOf(node),
|
|
11154
|
+
end: endLineOf(node)
|
|
11155
|
+
}
|
|
11156
|
+
};
|
|
11157
|
+
return { node, source, terminal };
|
|
11158
|
+
}
|
|
11159
|
+
function componentTargetOf(tagNode) {
|
|
11160
|
+
if (!Node46.isIdentifier(tagNode) || !/^[A-Z]/.test(tagNode.getText())) {
|
|
11161
|
+
return null;
|
|
11162
|
+
}
|
|
11163
|
+
const target = functionTargetOf(tagNode);
|
|
11164
|
+
return target === null ? null : { file: target.file, name: target.name };
|
|
11165
|
+
}
|
|
11166
|
+
function jsxToRenderNode(node) {
|
|
11167
|
+
if (Node46.isJsxElement(node)) {
|
|
11168
|
+
const opening = node.getOpeningElement();
|
|
11169
|
+
const tag = opening.getTagNameNode().getText();
|
|
11170
|
+
const attrs = collectJsxAttributes(opening);
|
|
11171
|
+
const target = componentTargetOf(opening.getTagNameNode());
|
|
11172
|
+
const children = node.getJsxChildren().map(jsxChildToRenderNode).filter((n) => n !== null);
|
|
11173
|
+
return {
|
|
11174
|
+
type: "element",
|
|
11175
|
+
tag,
|
|
11176
|
+
children,
|
|
11177
|
+
...attrs !== null ? { attrs } : {},
|
|
11178
|
+
...target !== null ? { target } : {}
|
|
11179
|
+
};
|
|
11180
|
+
}
|
|
11181
|
+
if (Node46.isJsxSelfClosingElement(node)) {
|
|
11182
|
+
const tag = node.getTagNameNode().getText();
|
|
11183
|
+
const attrs = collectJsxAttributes(node);
|
|
11184
|
+
const target = componentTargetOf(node.getTagNameNode());
|
|
11185
|
+
return {
|
|
11186
|
+
type: "element",
|
|
11187
|
+
tag,
|
|
11188
|
+
children: [],
|
|
11189
|
+
...attrs !== null ? { attrs } : {},
|
|
11190
|
+
...target !== null ? { target } : {}
|
|
11191
|
+
};
|
|
11192
|
+
}
|
|
11193
|
+
if (Node46.isJsxFragment(node)) {
|
|
11194
|
+
const children = node.getJsxChildren().map(jsxChildToRenderNode).filter((n) => n !== null);
|
|
11195
|
+
return { type: "element", tag: "Fragment", children };
|
|
11196
|
+
}
|
|
11197
|
+
if (Node46.isParenthesizedExpression(node)) {
|
|
11198
|
+
return jsxToRenderNode(node.getExpression());
|
|
11199
|
+
}
|
|
11200
|
+
return null;
|
|
11201
|
+
}
|
|
11202
|
+
function collectJsxAttributes(opening) {
|
|
11203
|
+
const entries = {};
|
|
11204
|
+
for (const attr of opening.getAttributes()) {
|
|
11205
|
+
if (Node46.isJsxSpreadAttribute(attr)) {
|
|
11206
|
+
const exprText = attr.getExpression().getText();
|
|
11207
|
+
entries[`...${exprText}`] = exprText;
|
|
11208
|
+
continue;
|
|
11209
|
+
}
|
|
11210
|
+
if (!Node46.isJsxAttribute(attr)) {
|
|
11211
|
+
continue;
|
|
11212
|
+
}
|
|
11213
|
+
const name = attr.getNameNode().getText();
|
|
11214
|
+
const initializer = attr.getInitializer();
|
|
11215
|
+
if (initializer === void 0) {
|
|
11216
|
+
entries[name] = "";
|
|
11217
|
+
continue;
|
|
11218
|
+
}
|
|
11219
|
+
if (Node46.isJsxExpression(initializer)) {
|
|
11220
|
+
const inner = initializer.getExpression();
|
|
11221
|
+
entries[name] = inner !== void 0 ? inner.getText() : "";
|
|
11222
|
+
continue;
|
|
11223
|
+
}
|
|
11224
|
+
entries[name] = initializer.getText();
|
|
11225
|
+
}
|
|
11226
|
+
return Object.keys(entries).length > 0 ? entries : null;
|
|
11227
|
+
}
|
|
11228
|
+
function jsxChildToRenderNode(child) {
|
|
11229
|
+
if (Node46.isJsxText(child)) {
|
|
11230
|
+
const text = child.getLiteralText().trim();
|
|
11231
|
+
if (text.length === 0) {
|
|
11232
|
+
return null;
|
|
11233
|
+
}
|
|
11234
|
+
return { type: "text", value: text };
|
|
11235
|
+
}
|
|
11236
|
+
if (Node46.isJsxExpression(child)) {
|
|
11237
|
+
const inner = child.getExpression();
|
|
11238
|
+
if (inner === void 0) {
|
|
11239
|
+
return null;
|
|
11240
|
+
}
|
|
11241
|
+
return jsxExpressionToRenderNode(inner);
|
|
11242
|
+
}
|
|
11243
|
+
if (Node46.isJsxElement(child) || Node46.isJsxSelfClosingElement(child) || Node46.isJsxFragment(child)) {
|
|
11244
|
+
return jsxToRenderNode(child);
|
|
11245
|
+
}
|
|
11246
|
+
return null;
|
|
11247
|
+
}
|
|
11248
|
+
function jsxExpressionToRenderNode(expr) {
|
|
11249
|
+
if (Node46.isParenthesizedExpression(expr)) {
|
|
11250
|
+
return jsxExpressionToRenderNode(expr.getExpression());
|
|
11251
|
+
}
|
|
11252
|
+
if (Node46.isBinaryExpression(expr)) {
|
|
11253
|
+
const op = expr.getOperatorToken().getText();
|
|
11254
|
+
if (op === "&&") {
|
|
11255
|
+
const right = renderAlternative(peelParens(expr.getRight()));
|
|
11256
|
+
if (right.kind === "jsx") {
|
|
11257
|
+
return {
|
|
11258
|
+
type: "conditional",
|
|
11259
|
+
condition: expr.getLeft().getText(),
|
|
11260
|
+
whenTrue: right.node,
|
|
11261
|
+
whenFalse: null
|
|
11262
|
+
};
|
|
11263
|
+
}
|
|
11264
|
+
}
|
|
11265
|
+
}
|
|
11266
|
+
if (Node46.isConditionalExpression(expr)) {
|
|
11267
|
+
const truthy = renderAlternative(peelParens(expr.getWhenTrue()));
|
|
11268
|
+
const falsy = renderAlternative(peelParens(expr.getWhenFalse()));
|
|
11269
|
+
if (truthy.kind === "jsx") {
|
|
11270
|
+
return {
|
|
11271
|
+
type: "conditional",
|
|
11272
|
+
condition: expr.getCondition().getText(),
|
|
11273
|
+
whenTrue: truthy.node,
|
|
11274
|
+
whenFalse: falsy.kind === "jsx" ? falsy.node : null
|
|
11275
|
+
};
|
|
11276
|
+
}
|
|
11277
|
+
if (falsy.kind === "jsx") {
|
|
11278
|
+
return {
|
|
11279
|
+
type: "conditional",
|
|
11280
|
+
condition: `!(${expr.getCondition().getText()})`,
|
|
11281
|
+
whenTrue: falsy.node,
|
|
11282
|
+
whenFalse: null
|
|
11283
|
+
};
|
|
11284
|
+
}
|
|
11285
|
+
}
|
|
11286
|
+
return { type: "expression", sourceText: expr.getText() };
|
|
11287
|
+
}
|
|
11288
|
+
function renderAlternative(node) {
|
|
11289
|
+
if (Node46.isNullLiteral(node)) {
|
|
11290
|
+
return { kind: "noRender" };
|
|
11291
|
+
}
|
|
11292
|
+
if (Node46.isFalseLiteral(node)) {
|
|
11293
|
+
return { kind: "noRender" };
|
|
11294
|
+
}
|
|
11295
|
+
if (Node46.isIdentifier(node) && node.getText() === "undefined") {
|
|
11296
|
+
return { kind: "noRender" };
|
|
11297
|
+
}
|
|
11298
|
+
if (Node46.isJsxElement(node) || Node46.isJsxSelfClosingElement(node) || Node46.isJsxFragment(node)) {
|
|
11299
|
+
const tree = jsxToRenderNode(node);
|
|
11300
|
+
if (tree !== null) {
|
|
11301
|
+
return { kind: "jsx", node: tree };
|
|
11302
|
+
}
|
|
11303
|
+
}
|
|
11304
|
+
return { kind: "notStatic" };
|
|
11305
|
+
}
|
|
11306
|
+
|
|
11307
|
+
// src/terminals/returns.ts
|
|
11308
|
+
import {
|
|
11309
|
+
Node as Node49
|
|
11310
|
+
} from "ts-morph";
|
|
11311
|
+
|
|
11288
11312
|
// src/terminals/helperResolution.ts
|
|
11289
11313
|
import { Node as Node47, SyntaxKind as SyntaxKind11 } from "ts-morph";
|
|
11290
11314
|
function resolveHelperReturn(call, resolveCallee2) {
|
|
@@ -11856,10 +11880,9 @@ function tryMatchReturnStatement(node, pattern, func, allPatterns) {
|
|
|
11856
11880
|
return null;
|
|
11857
11881
|
}
|
|
11858
11882
|
function buildReturnTerminal(locationNode, pattern, body) {
|
|
11859
|
-
const statusCode = pattern.extraction.defaultStatusCode !== void 0 ? { type: "literal", value: pattern.extraction.defaultStatusCode } : null;
|
|
11860
11883
|
const terminal = {
|
|
11861
11884
|
kind: pattern.kind,
|
|
11862
|
-
statusCode,
|
|
11885
|
+
statusCode: declaredStatusCode(pattern.extraction),
|
|
11863
11886
|
body,
|
|
11864
11887
|
exceptionType: null,
|
|
11865
11888
|
message: null,
|
|
@@ -12148,15 +12171,15 @@ function functionMayFallThrough(func) {
|
|
|
12148
12171
|
}
|
|
12149
12172
|
return true;
|
|
12150
12173
|
}
|
|
12151
|
-
function makeFallthroughTerminal(func) {
|
|
12174
|
+
function makeFallthroughTerminal(func, pattern) {
|
|
12152
12175
|
const body = func.getBody();
|
|
12153
12176
|
const anchor = body ?? func;
|
|
12154
12177
|
const line = endLineOf(anchor);
|
|
12155
12178
|
return {
|
|
12156
12179
|
node: anchor,
|
|
12157
12180
|
terminal: {
|
|
12158
|
-
kind:
|
|
12159
|
-
statusCode:
|
|
12181
|
+
kind: pattern.kind,
|
|
12182
|
+
statusCode: declaredStatusCode(pattern.extraction),
|
|
12160
12183
|
body: null,
|
|
12161
12184
|
exceptionType: null,
|
|
12162
12185
|
message: null,
|
|
@@ -12276,15 +12299,15 @@ function extractRawBranches(func, terminalPatterns, invocationRecognizers = [],
|
|
|
12276
12299
|
terminals.map(({ node }) => node),
|
|
12277
12300
|
barriers
|
|
12278
12301
|
);
|
|
12279
|
-
const
|
|
12302
|
+
const fallthroughPattern = terminalPatterns.find(
|
|
12280
12303
|
(p) => p.match.type === "functionFallthrough"
|
|
12281
12304
|
);
|
|
12282
|
-
if (
|
|
12305
|
+
if (fallthroughPattern !== void 0 && functionMayFallThrough(func)) {
|
|
12283
12306
|
const hasDefaultTerminal = terminals.some(
|
|
12284
12307
|
({ node }) => (byTerminal.get(node) ?? []).some(isDefaultConditionList)
|
|
12285
12308
|
);
|
|
12286
12309
|
if (!hasDefaultTerminal) {
|
|
12287
|
-
const synthetic = makeFallthroughTerminal(func);
|
|
12310
|
+
const synthetic = makeFallthroughTerminal(func, fallthroughPattern);
|
|
12288
12311
|
terminals.push(synthetic);
|
|
12289
12312
|
const pathResult = computePathConditions(
|
|
12290
12313
|
func,
|