@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.
Files changed (3) hide show
  1. package/dist/index.cjs +270 -247
  2. package/dist/index.js +266 -243
  3. 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 importedLocalName = resolveImportedLocalName(
8116
+ const spellings = importedReferenceSpellings(
8097
8117
  sourceFile,
8098
8118
  importModule,
8099
8119
  importName
8100
8120
  );
8101
8121
  const subjects = /* @__PURE__ */ new Map();
8102
- if (importedLocalName === null) {
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 === importedLocalName) {
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 (typeText === importedLocalName || typeText.startsWith(`${importedLocalName}<`)) {
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 importedLocalName = resolveImportedLocalName(
8191
+ const spellings = importedReferenceSpellings(
8170
8192
  sourceFile,
8171
8193
  importModule,
8172
8194
  importName
8173
8195
  );
8174
- if (importedLocalName === null) {
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() === importedLocalName && !Node32.isVariableDeclaration(node.getParent())) {
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/jsx.ts
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 Node49
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 Node45,
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 && Node45.isIdentifier(unwrapped2)) {
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 (Node45.isObjectLiteralExpression(unwrapped2)) {
10713
+ if (Node44.isObjectLiteralExpression(unwrapped2)) {
10879
10714
  return shapeFromObjectLiteral(unwrapped2);
10880
10715
  }
10881
- if (Node45.isArrayLiteralExpression(unwrapped2)) {
10716
+ if (Node44.isArrayLiteralExpression(unwrapped2)) {
10882
10717
  return shapeFromArrayLiteral(unwrapped2);
10883
10718
  }
10884
- if (Node45.isStringLiteral(unwrapped2) || Node45.isNoSubstitutionTemplateLiteral(unwrapped2)) {
10719
+ if (Node44.isStringLiteral(unwrapped2) || Node44.isNoSubstitutionTemplateLiteral(unwrapped2)) {
10885
10720
  return { type: "literal", value: unwrapped2.getLiteralValue() };
10886
10721
  }
10887
- if (Node45.isTemplateExpression(unwrapped2)) {
10722
+ if (Node44.isTemplateExpression(unwrapped2)) {
10888
10723
  return { type: "text" };
10889
10724
  }
10890
- if (Node45.isNumericLiteral(unwrapped2)) {
10725
+ if (Node44.isNumericLiteral(unwrapped2)) {
10891
10726
  return numericLiteralShape(
10892
10727
  unwrapped2.getLiteralValue(),
10893
10728
  unwrapped2.getText()
10894
10729
  );
10895
10730
  }
10896
- if (Node45.isPrefixUnaryExpression(unwrapped2)) {
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 (Node45.isNumericLiteral(inner)) {
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 (Node45.isBigIntLiteral(unwrapped2)) {
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 (Node45.isIdentifier(unwrapped2) && unwrapped2.getText() === "undefined") {
10757
+ if (Node44.isIdentifier(unwrapped2) && unwrapped2.getText() === "undefined") {
10923
10758
  return { type: "undefined" };
10924
10759
  }
10925
- if (Node45.isConditionalExpression(unwrapped2)) {
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 (Node45.isSpreadElement(el)) {
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 (Node45.isPropertyAssignment(prop)) {
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 (Node45.isShorthandPropertyAssignment(prop)) {
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 (Node45.isSpreadAssignment(prop)) {
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 (Node45.isIdentifier(nameNode) || Node45.isStringLiteral(nameNode) || Node45.isNoSubstitutionTemplateLiteral(nameNode) || Node45.isNumericLiteral(nameNode)) {
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 (!Node46.isCallExpression(outer)) {
10885
+ if (!Node45.isCallExpression(outer)) {
11055
10886
  return node;
11056
10887
  }
11057
10888
  const callee = outer.getExpression();
11058
- if (!Node46.isPropertyAccessExpression(callee) || callee.getName() !== "stringify") {
10889
+ if (!Node45.isPropertyAccessExpression(callee) || callee.getName() !== "stringify") {
11059
10890
  return node;
11060
10891
  }
11061
10892
  const receiver = callee.getExpression();
11062
- if (!Node46.isIdentifier(receiver) || receiver.getText() !== "JSON") {
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 || !Node46.isIdentifier(value)) {
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
- if (ctx.extraction.defaultStatusCode !== void 0) {
11086
- return { type: "literal", value: ctx.extraction.defaultStatusCode };
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 (Node46.isShorthandPropertyAssignment(prop)) {
10947
+ if (Node45.isShorthandPropertyAssignment(prop)) {
11117
10948
  return { type: "dynamic", sourceText: prop.getName() };
11118
10949
  }
11119
- if (!Node46.isPropertyAssignment(prop)) {
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 && Node46.isNumericLiteral(first)) {
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 || !Node46.isNewExpression(arg)) {
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 || !Node46.isObjectLiteralExpression(arg)) {
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 (!Node46.isPropertyAssignment(prop)) {
11175
- if (Node46.isShorthandPropertyAssignment(prop)) {
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 (!Node46.isPropertyAssignment(prop)) {
11234
- if (Node46.isShorthandPropertyAssignment(prop)) {
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: "return",
12159
- statusCode: null,
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 wantsFallthrough = terminalPatterns.some(
12302
+ const fallthroughPattern = terminalPatterns.find(
12280
12303
  (p) => p.match.type === "functionFallthrough"
12281
12304
  );
12282
- if (wantsFallthrough && functionMayFallThrough(func)) {
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,