@systemfsoftware/stryker-js-instrumenter 7.0.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,3 @@
1
- import { INSTRUMENTER_CONSTANTS, Mutant } from "@systemfsoftware/stryker-js-language";
2
1
  import * as Effect from "effect/Effect";
3
2
  import * as Predicate from "effect/Predicate";
4
3
  import * as S from "effect/Schema";
@@ -8,6 +7,59 @@ import * as Option from "effect/Option";
8
7
  import { walk } from "oxc-walker";
9
8
  import { Schema } from "effect";
10
9
  import { RegExpParser, visitRegExpAST } from "@eslint-community/regexpp";
10
+ //#region src/Location.schema.ts
11
+ const PositionSchema = S.Struct({
12
+ line: S.Finite,
13
+ column: S.Finite
14
+ });
15
+ const LocationSchema = S.Struct({
16
+ start: PositionSchema,
17
+ end: PositionSchema
18
+ });
19
+ const OpenEndLocationSchema = S.Struct({
20
+ start: PositionSchema,
21
+ end: S.optional(PositionSchema)
22
+ });
23
+ //#endregion
24
+ //#region src/Mutant.schema.ts
25
+ const MutantStatusSchema = S.Literals([
26
+ "Killed",
27
+ "Survived",
28
+ "NoCoverage",
29
+ "CompileError",
30
+ "RuntimeError",
31
+ "Timeout",
32
+ "Ignored",
33
+ "Pending"
34
+ ]);
35
+ var Mutant = class extends S.TaggedClass()("Mutant", {
36
+ id: S.NonEmptyString,
37
+ fileName: S.NonEmptyString,
38
+ mutatorName: S.NonEmptyString,
39
+ replacement: S.String,
40
+ location: LocationSchema,
41
+ status: S.optional(MutantStatusSchema),
42
+ statusReason: S.optional(S.String),
43
+ coveredBy: S.optional(S.Array(S.String)),
44
+ static: S.optional(S.Boolean),
45
+ testsCompleted: S.optional(S.Finite),
46
+ description: S.optional(S.String)
47
+ }) {};
48
+ const RunOptionsFields = {
49
+ timeout: S.Finite,
50
+ disableBail: S.Boolean
51
+ };
52
+ const MutantActivationSchema = S.Literals(["runtime", "static"]);
53
+ const MutantRunOptionsSchema = S.Struct({
54
+ ...RunOptionsFields,
55
+ activeMutant: Mutant,
56
+ sandboxFileName: S.String,
57
+ mutantActivation: MutantActivationSchema,
58
+ reloadEnvironment: S.Boolean,
59
+ testFilter: S.optionalKey(S.Array(S.String)),
60
+ hitLimit: S.optionalKey(S.Finite)
61
+ });
62
+ //#endregion
11
63
  //#region src/Instrument.schema.ts
12
64
  var InstrumentError = class extends S.TaggedError("@systemfsoftware/stryker-js-instrumenter/Instrument.schema/InstrumentError")("InstrumentError", {
13
65
  message: S.String,
@@ -18,13 +70,13 @@ var InstrumentError = class extends S.TaggedError("@systemfsoftware/stryker-js-i
18
70
  return this.message;
19
71
  }
20
72
  };
21
- const PositionSchema = S.Struct({
73
+ const PositionSchema$1 = S.Struct({
22
74
  line: S.Finite,
23
75
  column: S.Finite
24
76
  });
25
77
  const RangeSchema = S.Struct({
26
- start: PositionSchema,
27
- end: PositionSchema
78
+ start: PositionSchema$1,
79
+ end: PositionSchema$1
28
80
  });
29
81
  const MutateDescriptionSchema = S.Union([S.Boolean, S.Array(RangeSchema)]);
30
82
  const FileSchema = S.Struct({
@@ -33,7 +85,7 @@ const FileSchema = S.Struct({
33
85
  mutate: MutateDescriptionSchema
34
86
  });
35
87
  const IgnorerSchema = S.Unknown;
36
- S.Struct({
88
+ const InstrumenterOptionsSchema = S.Struct({
37
89
  excludedMutations: S.Array(S.String),
38
90
  ignorers: S.Array(IgnorerSchema),
39
91
  noHeader: S.optional(S.Boolean)
@@ -52,6 +104,9 @@ S.Literals([
52
104
  //#endregion
53
105
  //#region src/Syntax.ts
54
106
  /**
107
+ * Syntax — the instrumenter's AST shapes, location helpers and syntax utilities.
108
+ */
109
+ /**
55
110
  * Determines if a location (needle) is included in an other location (haystack)
56
111
  * @param haystack The range to look in
57
112
  * @param needle the range to search for
@@ -264,7 +319,7 @@ function memberExpression(object, property, optional, loc) {
264
319
  }, loc);
265
320
  }
266
321
  function arrowFunctionExpression(params, body, loc) {
267
- const fnBody = body;
322
+ const fnBody = arrowFunctionBody(body);
268
323
  return mark({
269
324
  type: "ArrowFunctionExpression",
270
325
  id: null,
@@ -275,6 +330,16 @@ function arrowFunctionExpression(params, body, loc) {
275
330
  expression: fnBody.type !== "BlockStatement"
276
331
  }, loc);
277
332
  }
333
+ function arrowFunctionBody(body) {
334
+ if (isArrowBody(body)) return body;
335
+ throw new Error(`Invalid arrow function body: ${body.type}`);
336
+ }
337
+ function isArrowBody(body) {
338
+ return isBlockStatementNode(body) || isExpressionKind(body);
339
+ }
340
+ function isBlockStatementNode(node) {
341
+ return nodeType(node) === "BlockStatement";
342
+ }
278
343
  function blockStatement(body, loc) {
279
344
  return mark({
280
345
  type: "BlockStatement",
@@ -426,9 +491,13 @@ function pushComment(map, node, comment) {
426
491
  else list.push(comment);
427
492
  }
428
493
  const isNodeList = (value) => Array.isArray(value);
494
+ const walkableNode = (node) => {
495
+ if (isAstNode(node)) return node;
496
+ throw new Error("Expected an AST node to walk");
497
+ };
429
498
  const walker = (root, visitors) => {
430
499
  const ancestors = [];
431
- walk(root, {
500
+ walk(walkableNode(root), {
432
501
  enter(node) {
433
502
  visitors.enter?.(node, [...ancestors]);
434
503
  ancestors.push(node);
@@ -475,7 +544,7 @@ function isCommentKey(key) {
475
544
  function traverse(root, visitors) {
476
545
  const stack = [];
477
546
  try {
478
- walk(root, {
547
+ walk(walkableNode(root), {
479
548
  enter(node, _parent, context) {
480
549
  readPath(stack, node, this, context, visitors);
481
550
  },
@@ -508,8 +577,11 @@ function notify(visitor, path) {
508
577
  const relay = (visitor, path) => {
509
578
  if (path !== void 0) visitor(path);
510
579
  };
580
+ const keyOf = (context) => {
581
+ if (typeof context.key === "string") return context.key;
582
+ };
511
583
  function createPath(node, parentPath, controls, context) {
512
- const key = typeof context.key === "string" ? context.key : void 0;
584
+ const key = keyOf(context);
513
585
  const path = {
514
586
  node,
515
587
  parentPath,
@@ -649,7 +721,7 @@ function hasContent(value) {
649
721
  function hasHtml(value) {
650
722
  return hasField(value, "html");
651
723
  }
652
- function fieldOf(value, key) {
724
+ function fieldOf$1(value, key) {
653
725
  return Match.value(value).pipe(Match.when(isPlainRecord, (record) => record[key]), Match.orElse(() => void 0));
654
726
  }
655
727
  function appendIfDefined(values, value) {
@@ -733,7 +805,8 @@ const dotBeforeSlash = (dot, slash) => dot >= 0 && dot > slash;
733
805
  const extensionOf = (fileName) => {
734
806
  const dot = fileName.lastIndexOf(".");
735
807
  const slash = Math.max(fileName.lastIndexOf("/"), fileName.lastIndexOf("\\"));
736
- return dotBeforeSlash(dot, slash) ? fileName.slice(dot).toLowerCase() : "";
808
+ if (!dotBeforeSlash(dot, slash)) return "";
809
+ return fileName.slice(dot).toLowerCase();
737
810
  };
738
811
  function createJSParser() {
739
812
  return (text, fileName) => Effect.map(parseWithOxc(text, fileName, "js"), ({ root, comments }) => ({
@@ -1040,7 +1113,7 @@ function htmlRootOf(ast) {
1040
1113
  }));
1041
1114
  }
1042
1115
  function instanceScriptRange(ast) {
1043
- return Match.value(fieldOf(ast, "instance")).pipe(Match.when(hasContent, (instance) => scriptContentRange(instance["content"], INSTANCE_RANGE_MISSING)), Match.orElse(() => void 0));
1116
+ return Match.value(fieldOf$1(ast, "instance")).pipe(Match.when(hasContent, (instance) => scriptContentRange(instance["content"], INSTANCE_RANGE_MISSING)), Match.orElse(() => void 0));
1044
1117
  }
1045
1118
  function scriptContentRange(content, missingRange) {
1046
1119
  return Match.value(content).pipe(Match.when(isRange, (range) => ({
@@ -1052,7 +1125,7 @@ function scriptContentRange(content, missingRange) {
1052
1125
  }));
1053
1126
  }
1054
1127
  function getModuleScriptRange(svelteAst) {
1055
- return Match.value(fieldOf(svelteAst, "module")).pipe(Match.when(void 0, () => void 0), Match.when(null, () => void 0), Match.orElse((block) => moduleBlockRange(block)));
1128
+ return Match.value(fieldOf$1(svelteAst, "module")).pipe(Match.when(void 0, () => void 0), Match.when(null, () => void 0), Match.orElse((block) => moduleBlockRange(block)));
1056
1129
  }
1057
1130
  function moduleBlockRange(block) {
1058
1131
  return Match.value(block).pipe(Match.when(hasContent, (record) => scriptContentRange(record["content"], MODULE_RANGE_MISSING)), Match.orElse(() => {
@@ -1110,10 +1183,10 @@ function scriptFormatOf(script) {
1110
1183
  //#endregion
1111
1184
  //#region src/print/index.ts
1112
1185
  function printProgram(program, opts = {}) {
1113
- return new PrintState(opts).printProgram(program);
1186
+ return renderProgram(createState(opts), program);
1114
1187
  }
1115
1188
  function printNode(node, opts = {}) {
1116
- return new PrintState(opts).printAnyNode(node);
1189
+ return renderAnyNode(createState(opts), node);
1117
1190
  }
1118
1191
  const PREC = {
1119
1192
  Sequence: 0,
@@ -1175,1740 +1248,1728 @@ const LOGICAL_PRECEDENCE = {
1175
1248
  function logicalPrec(op) {
1176
1249
  return LOGICAL_PRECEDENCE[op] ?? PREC.LogicalAND;
1177
1250
  }
1178
- var PrintState = class {
1179
- out = "";
1180
- indentLevel = 0;
1181
- hashbang;
1182
- commentIdx = 0;
1183
- sortedComments;
1184
- constructor(opts) {
1185
- this.hashbang = opts.hashbang ?? null;
1186
- this.sortedComments = [...sortedCommentsWithoutHashbang(opts.comments, this.hashbang), END_OF_COMMENTS];
1187
- }
1188
- printProgram(program) {
1189
- this.out = "";
1190
- this.indentLevel = 0;
1191
- this.commentIdx = 0;
1192
- this.printHashbang();
1193
- this.emitCommentsBefore(program.body[0]?.start);
1194
- this.printProgramBody(program.body);
1195
- this.emitCommentsBefore(void 0);
1196
- return this.out;
1197
- }
1198
- printAnyNode(node) {
1199
- this.out = "";
1200
- this.indentLevel = 0;
1201
- this.printNode(node, PREC.Sequence);
1202
- return this.out;
1203
- }
1204
- printHashbang() {
1205
- if (this.hashbang) this.out += `#!${this.hashbang.value}\n`;
1206
- }
1207
- printProgramBody(body) {
1208
- body.forEach((statement) => this.printProgramStatement(statement));
1209
- }
1210
- printProgramStatement(statement) {
1211
- this.emitCommentsBefore(statement.start ?? -1);
1212
- this.printStatement(statement);
1213
- this.out += "\n";
1214
- }
1215
- printJumpStatement(keyword, label) {
1216
- this.out += keyword;
1217
- if (label) this.out += ` ${label.name}`;
1218
- this.out += ";";
1219
- }
1220
- /** Emits every pending comment that starts before `pos`; an absent bound admits every comment. */
1221
- emitCommentsBefore(pos) {
1222
- this.emitPendingCommentsBefore(pos ?? EVERY_COMMENT_POSITION);
1223
- }
1224
- emitPendingCommentsBefore(pos) {
1225
- for (let comment = this.sortedComments[this.commentIdx]; comment.start < pos; comment = this.sortedComments[this.commentIdx]) {
1226
- this.emitComment(comment);
1227
- this.commentIdx++;
1228
- }
1229
- }
1230
- emitComment(c) {
1231
- if (c.type === "Line") this.out += `//${c.value}\n`;
1232
- else this.out += `/*${c.value}*/\n`;
1233
- }
1234
- indent() {
1235
- return " ".repeat(this.indentLevel);
1236
- }
1237
- nl() {
1238
- this.out += "\n";
1239
- }
1240
- /** Renders a fragment to a string without disturbing the pending output. */
1241
- capture(render) {
1242
- const saved = this.out;
1243
- this.out = "";
1244
- render();
1245
- const result = this.out;
1246
- this.out = saved;
1247
- return result;
1248
- }
1249
- needsParens(childPrec, parentPrec, isRight, op) {
1250
- switch (childPrec === parentPrec) {
1251
- case true: return this.equalPrecedenceNeedsParens(isRight, op);
1252
- default: return childPrec < parentPrec;
1253
- }
1254
- }
1255
- /** Equal precedence — associativity decides. */
1256
- equalPrecedenceNeedsParens(isRight, op) {
1257
- switch (op) {
1258
- case "**": return !isRight;
1259
- default: return isRight;
1260
- }
1261
- }
1262
- wrapIfNeeded(node, prec, parentPrec, isRight, op) {
1263
- const inner = this.printExpressionToString(node, prec);
1264
- if (this.needsParens(prec, parentPrec, isRight, op)) return `(${inner})`;
1265
- return inner;
1266
- }
1267
- printExpressionToString(node, prec) {
1268
- return this.capture(() => this.printNode(node, prec));
1269
- }
1270
- sequenceNodeText(node) {
1271
- return this.capture(() => this.printNode(node, PREC.Sequence));
1272
- }
1273
- assignmentNodeText(node) {
1274
- return this.capture(() => this.printNode(node, PREC.Assignment));
1251
+ function createState(opts) {
1252
+ const hashbang = opts.hashbang ?? null;
1253
+ return {
1254
+ out: "",
1255
+ indentLevel: 0,
1256
+ hashbang,
1257
+ commentIdx: 0,
1258
+ sortedComments: [...sortedCommentsWithoutHashbang(opts.comments, hashbang), END_OF_COMMENTS]
1259
+ };
1260
+ }
1261
+ function renderProgram(state, program) {
1262
+ state.out = "";
1263
+ state.indentLevel = 0;
1264
+ state.commentIdx = 0;
1265
+ printHashbang(state);
1266
+ emitCommentsBefore(state, program.body[0]?.start);
1267
+ printProgramBody(state, program.body);
1268
+ emitCommentsBefore(state, void 0);
1269
+ return state.out;
1270
+ }
1271
+ function renderAnyNode(state, node) {
1272
+ state.out = "";
1273
+ state.indentLevel = 0;
1274
+ printNodePrec(state, node, PREC.Sequence);
1275
+ return state.out;
1276
+ }
1277
+ function printHashbang(state) {
1278
+ if (state.hashbang !== null) state.out += `#!${state.hashbang.value}\n`;
1279
+ }
1280
+ function printProgramBody(state, body) {
1281
+ body.forEach((statement) => printProgramStatement(state, statement));
1282
+ }
1283
+ function printProgramStatement(state, statement) {
1284
+ emitCommentsBefore(state, statement.start ?? -1);
1285
+ printStatement(state, statement);
1286
+ state.out += "\n";
1287
+ }
1288
+ function printJumpStatement(state, keyword, label) {
1289
+ state.out += keyword;
1290
+ if (label !== null) state.out += ` ${label.name}`;
1291
+ state.out += ";";
1292
+ }
1293
+ function emitCommentsBefore(state, pos) {
1294
+ emitPendingCommentsBefore(state, pos ?? EVERY_COMMENT_POSITION);
1295
+ }
1296
+ function emitPendingCommentsBefore(state, pos) {
1297
+ let comment = state.sortedComments[state.commentIdx];
1298
+ while (isCommentBefore(comment, pos)) {
1299
+ emitComment(state, comment);
1300
+ state.commentIdx++;
1301
+ comment = state.sortedComments[state.commentIdx];
1302
+ }
1303
+ }
1304
+ function isCommentBefore(comment, pos) {
1305
+ return comment !== void 0 && comment.start < pos;
1306
+ }
1307
+ function emitComment(state, c) {
1308
+ if (c.type === "Line") state.out += `//${c.value}\n`;
1309
+ else state.out += `/*${c.value}*/\n`;
1310
+ }
1311
+ function indent(state) {
1312
+ return " ".repeat(state.indentLevel);
1313
+ }
1314
+ function capture(state, render) {
1315
+ const saved = state.out;
1316
+ state.out = "";
1317
+ render();
1318
+ const result = state.out;
1319
+ state.out = saved;
1320
+ return result;
1321
+ }
1322
+ function needsParens(childPrec, parentPrec, isRight, op) {
1323
+ if (childPrec === parentPrec) return equalPrecedenceNeedsParens(isRight, op);
1324
+ return childPrec < parentPrec;
1325
+ }
1326
+ function equalPrecedenceNeedsParens(isRight, op) {
1327
+ if (op === "**") return !isRight;
1328
+ return isRight;
1329
+ }
1330
+ function wrapIfNeeded(state, node, prec, parentPrec, isRight, op) {
1331
+ const inner = printExpressionToString(state, node, prec);
1332
+ if (needsParens(prec, parentPrec, isRight, op)) return `(${inner})`;
1333
+ return inner;
1334
+ }
1335
+ function printExpressionToString(state, node, prec) {
1336
+ return capture(state, () => printNodePrec(state, node, prec));
1337
+ }
1338
+ function sequenceNodeText(state, node) {
1339
+ return capture(state, () => printNodePrec(state, node, PREC.Sequence));
1340
+ }
1341
+ function assignmentNodeText(state, node) {
1342
+ return capture(state, () => printNodePrec(state, node, PREC.Assignment));
1343
+ }
1344
+ function nodeListText(state, nodes, prec) {
1345
+ return nodes.map((node) => capture(state, () => printNodePrec(state, node, prec))).join(", ");
1346
+ }
1347
+ function wrappedExpressionText(state, node, prec, wrappedKinds) {
1348
+ const printed = printExpressionToString(state, node, prec);
1349
+ if (wrappedKinds[node.type] === true) return `(${printed})`;
1350
+ return printed;
1351
+ }
1352
+ function printNodePrec(state, node, prec) {
1353
+ if (node == null) return;
1354
+ dispatchNode(state, node, prec);
1355
+ }
1356
+ function dispatchNode(state, node, prec) {
1357
+ switch (node.type) {
1358
+ case "Literal":
1359
+ printLiteral(state, node);
1360
+ break;
1361
+ case "Identifier":
1362
+ printIdentifier(state, node);
1363
+ break;
1364
+ case "PrivateIdentifier":
1365
+ state.out += `#${node.name}`;
1366
+ break;
1367
+ case "ThisExpression":
1368
+ state.out += "this";
1369
+ break;
1370
+ case "Super":
1371
+ state.out += "super";
1372
+ break;
1373
+ case "ArrayExpression":
1374
+ printArrayExpression(state, node);
1375
+ break;
1376
+ case "ObjectExpression":
1377
+ printObjectExpression(state, node);
1378
+ break;
1379
+ case "Property":
1380
+ printProperty(state, node);
1381
+ break;
1382
+ case "TemplateLiteral":
1383
+ printTemplateLiteral(state, node);
1384
+ break;
1385
+ case "TemplateElement":
1386
+ state.out += node.value.raw;
1387
+ break;
1388
+ case "TaggedTemplateExpression":
1389
+ printTaggedTemplate(state, node);
1390
+ break;
1391
+ case "MemberExpression":
1392
+ printMemberExpression(state, node, prec);
1393
+ break;
1394
+ case "CallExpression":
1395
+ printCallExpression(state, node, prec);
1396
+ break;
1397
+ case "NewExpression":
1398
+ printNewExpression(state, node, prec);
1399
+ break;
1400
+ case "MetaProperty":
1401
+ printMetaProperty(state, node);
1402
+ break;
1403
+ case "SpreadElement":
1404
+ state.out += "...";
1405
+ printNodePrec(state, node.argument, PREC.Assignment);
1406
+ break;
1407
+ case "RestElement":
1408
+ state.out += "...";
1409
+ printNodePrec(state, node.argument, PREC.Assignment);
1410
+ break;
1411
+ case "UpdateExpression":
1412
+ printUpdateExpression(state, node, prec);
1413
+ break;
1414
+ case "UnaryExpression":
1415
+ printUnaryExpression(state, node, prec);
1416
+ break;
1417
+ case "BinaryExpression":
1418
+ printBinaryExpression(state, node, prec);
1419
+ break;
1420
+ case "LogicalExpression":
1421
+ printLogicalExpression(state, node, prec);
1422
+ break;
1423
+ case "ConditionalExpression":
1424
+ printConditionalExpression(state, node, prec);
1425
+ break;
1426
+ case "AssignmentExpression":
1427
+ printAssignmentExpression(state, node, prec);
1428
+ break;
1429
+ case "AssignmentPattern":
1430
+ printAssignmentPattern(state, node, prec);
1431
+ break;
1432
+ case "ObjectPattern":
1433
+ printObjectPattern(state, node);
1434
+ break;
1435
+ case "ArrayPattern":
1436
+ printArrayPattern(state, node);
1437
+ break;
1438
+ case "SequenceExpression":
1439
+ printSequenceExpression(state, node, prec);
1440
+ break;
1441
+ case "AwaitExpression":
1442
+ state.out += "await ";
1443
+ printNodePrec(state, node.argument, PREC.Unary);
1444
+ break;
1445
+ case "YieldExpression":
1446
+ printYieldExpression(state, node, prec);
1447
+ break;
1448
+ case "ChainExpression":
1449
+ printNodePrec(state, node.expression, prec);
1450
+ break;
1451
+ case "ParenthesizedExpression":
1452
+ state.out += "(";
1453
+ printNodePrec(state, node.expression, PREC.Sequence);
1454
+ state.out += ")";
1455
+ break;
1456
+ case "ImportExpression":
1457
+ printImportExpression(state, node);
1458
+ break;
1459
+ case "V8IntrinsicExpression":
1460
+ printV8Intrinsic(state, node);
1461
+ break;
1462
+ case "ArrowFunctionExpression":
1463
+ printArrowFunction(state, node, prec);
1464
+ break;
1465
+ case "FunctionExpression":
1466
+ case "FunctionDeclaration":
1467
+ case "TSDeclareFunction":
1468
+ case "TSEmptyBodyFunctionExpression":
1469
+ printFunction(state, node, prec);
1470
+ break;
1471
+ case "ClassDeclaration":
1472
+ case "ClassExpression":
1473
+ printClass(state, node, prec);
1474
+ break;
1475
+ case "JSXElement":
1476
+ printJSXElement(state, node);
1477
+ break;
1478
+ case "JSXFragment":
1479
+ printJSXFragment(state, node);
1480
+ break;
1481
+ case "JSXOpeningElement":
1482
+ printJSXOpeningElement(state, node);
1483
+ break;
1484
+ case "JSXClosingElement": break;
1485
+ case "JSXIdentifier":
1486
+ state.out += node.name;
1487
+ break;
1488
+ case "JSXNamespacedName":
1489
+ state.out += `${node.namespace.name}:${node.name.name}`;
1490
+ break;
1491
+ case "JSXMemberExpression":
1492
+ printJSXMemberExpression(state, node);
1493
+ break;
1494
+ case "JSXAttribute":
1495
+ printJSXAttribute(state, node);
1496
+ break;
1497
+ case "JSXSpreadAttribute":
1498
+ state.out += "{...";
1499
+ printNodePrec(state, node.argument, PREC.Assignment);
1500
+ state.out += "}";
1501
+ break;
1502
+ case "JSXExpressionContainer":
1503
+ state.out += "{";
1504
+ printNodePrec(state, node.expression, PREC.Sequence);
1505
+ state.out += "}";
1506
+ break;
1507
+ case "JSXEmptyExpression": break;
1508
+ case "JSXText":
1509
+ state.out += node.value;
1510
+ break;
1511
+ case "JSXSpreadChild":
1512
+ state.out += "{...";
1513
+ printNodePrec(state, node.expression, PREC.Assignment);
1514
+ state.out += "}";
1515
+ break;
1516
+ case "TSAsExpression":
1517
+ printTSAsExpression(state, node, prec);
1518
+ break;
1519
+ case "TSSatisfiesExpression":
1520
+ printTSSatisfiesExpression(state, node, prec);
1521
+ break;
1522
+ case "TSTypeAssertion":
1523
+ printTSTypeAssertion(state, node, prec);
1524
+ break;
1525
+ case "TSNonNullExpression":
1526
+ printNodePrec(state, node.expression, PREC.Member);
1527
+ state.out += "!";
1528
+ break;
1529
+ case "TSInstantiationExpression":
1530
+ printTSInstantiationExpression(state, node, prec);
1531
+ break;
1532
+ case "BlockStatement":
1533
+ printBlockStatement(state, node);
1534
+ break;
1535
+ case "EmptyStatement":
1536
+ state.out += ";";
1537
+ break;
1538
+ case "ExpressionStatement":
1539
+ printExpressionStatement(state, node);
1540
+ break;
1541
+ case "IfStatement":
1542
+ printIfStatement(state, node);
1543
+ break;
1544
+ case "DoWhileStatement":
1545
+ printDoWhileStatement(state, node);
1546
+ break;
1547
+ case "WhileStatement":
1548
+ printWhileStatement(state, node);
1549
+ break;
1550
+ case "ForStatement":
1551
+ printForStatement(state, node);
1552
+ break;
1553
+ case "ForInStatement":
1554
+ printForInStatement(state, node);
1555
+ break;
1556
+ case "ForOfStatement":
1557
+ printForOfStatement(state, node);
1558
+ break;
1559
+ case "ContinueStatement":
1560
+ printJumpStatement(state, "continue", node.label);
1561
+ break;
1562
+ case "BreakStatement":
1563
+ printJumpStatement(state, "break", node.label);
1564
+ break;
1565
+ case "ReturnStatement":
1566
+ printReturnStatement(state, node);
1567
+ break;
1568
+ case "WithStatement":
1569
+ printWithStatement(state, node);
1570
+ break;
1571
+ case "SwitchStatement":
1572
+ printSwitchStatement(state, node);
1573
+ break;
1574
+ case "SwitchCase": break;
1575
+ case "LabeledStatement":
1576
+ printLabeledStatement(state, node);
1577
+ break;
1578
+ case "ThrowStatement":
1579
+ state.out += "throw ";
1580
+ printNodePrec(state, node.argument, PREC.Sequence);
1581
+ state.out += ";";
1582
+ break;
1583
+ case "TryStatement":
1584
+ printTryStatement(state, node);
1585
+ break;
1586
+ case "CatchClause": break;
1587
+ case "DebuggerStatement":
1588
+ state.out += "debugger;";
1589
+ break;
1590
+ case "VariableDeclaration":
1591
+ printVariableDeclaration(state, node);
1592
+ break;
1593
+ case "VariableDeclarator":
1594
+ printVariableDeclarator(state, node);
1595
+ break;
1596
+ case "ClassBody":
1597
+ printClassBody(state, node);
1598
+ break;
1599
+ case "MethodDefinition":
1600
+ case "TSAbstractMethodDefinition":
1601
+ printMethodDefinition(state, node);
1602
+ break;
1603
+ case "PropertyDefinition":
1604
+ case "TSAbstractPropertyDefinition":
1605
+ printPropertyDefinition(state, node);
1606
+ break;
1607
+ case "AccessorProperty":
1608
+ case "TSAbstractAccessorProperty":
1609
+ printAccessorProperty(state, node);
1610
+ break;
1611
+ case "StaticBlock":
1612
+ printStaticBlock(state, node);
1613
+ break;
1614
+ case "ImportDeclaration":
1615
+ printImportDeclaration(state, node);
1616
+ break;
1617
+ case "ExportNamedDeclaration":
1618
+ printExportNamedDeclaration(state, node);
1619
+ break;
1620
+ case "ExportDefaultDeclaration":
1621
+ printExportDefaultDeclaration(state, node);
1622
+ break;
1623
+ case "ExportAllDeclaration":
1624
+ printExportAllDeclaration(state, node);
1625
+ break;
1626
+ case "Decorator":
1627
+ state.out += "@";
1628
+ printNodePrec(state, node.expression, PREC.Member);
1629
+ break;
1630
+ case "TSTypeAliasDeclaration":
1631
+ printTSTypeAliasDeclaration(state, node);
1632
+ break;
1633
+ case "TSInterfaceDeclaration":
1634
+ printTSInterfaceDeclaration(state, node);
1635
+ break;
1636
+ case "TSEnumDeclaration":
1637
+ printTSEnumDeclaration(state, node);
1638
+ break;
1639
+ case "TSModuleDeclaration":
1640
+ printTSModuleDeclaration(state, node);
1641
+ break;
1642
+ case "TSImportEqualsDeclaration":
1643
+ printTSImportEqualsDeclaration(state, node);
1644
+ break;
1645
+ case "TSExportAssignment":
1646
+ state.out += `export = `;
1647
+ printNodePrec(state, node.expression, PREC.Sequence);
1648
+ state.out += ";";
1649
+ break;
1650
+ case "TSNamespaceExportDeclaration":
1651
+ state.out += `export as namespace ${node.id.name};`;
1652
+ break;
1653
+ case "Program":
1654
+ case "ExportSpecifier":
1655
+ case "Hashbang":
1656
+ case "ImportAttribute":
1657
+ case "ImportDefaultSpecifier":
1658
+ case "ImportNamespaceSpecifier":
1659
+ case "ImportSpecifier":
1660
+ case "JSXClosingFragment":
1661
+ case "JSXOpeningFragment":
1662
+ case "TSAnyKeyword":
1663
+ case "TSArrayType":
1664
+ case "TSBigIntKeyword":
1665
+ case "TSBooleanKeyword":
1666
+ case "TSCallSignatureDeclaration":
1667
+ case "TSClassImplements":
1668
+ case "TSConditionalType":
1669
+ case "TSConstructSignatureDeclaration":
1670
+ case "TSConstructorType":
1671
+ case "TSEnumBody":
1672
+ case "TSEnumMember":
1673
+ case "TSExternalModuleReference":
1674
+ case "TSFunctionType":
1675
+ case "TSImportType":
1676
+ case "TSIndexSignature":
1677
+ case "TSIndexedAccessType":
1678
+ case "TSInferType":
1679
+ case "TSInterfaceBody":
1680
+ case "TSInterfaceHeritage":
1681
+ case "TSIntersectionType":
1682
+ case "TSIntrinsicKeyword":
1683
+ case "TSJSDocNonNullableType":
1684
+ case "TSJSDocNullableType":
1685
+ case "TSJSDocUnknownType":
1686
+ case "TSLiteralType":
1687
+ case "TSMappedType":
1688
+ case "TSMethodSignature":
1689
+ case "TSModuleBlock":
1690
+ case "TSNamedTupleMember":
1691
+ case "TSNeverKeyword":
1692
+ case "TSNullKeyword":
1693
+ case "TSNumberKeyword":
1694
+ case "TSObjectKeyword":
1695
+ case "TSOptionalType":
1696
+ case "TSParameterProperty":
1697
+ case "TSParenthesizedType":
1698
+ case "TSPropertySignature":
1699
+ case "TSQualifiedName":
1700
+ case "TSRestType":
1701
+ case "TSStringKeyword":
1702
+ case "TSSymbolKeyword":
1703
+ case "TSTemplateLiteralType":
1704
+ case "TSThisType":
1705
+ case "TSTupleType":
1706
+ case "TSTypeAnnotation":
1707
+ case "TSTypeLiteral":
1708
+ case "TSTypeOperator":
1709
+ case "TSTypeParameter":
1710
+ case "TSTypeParameterDeclaration":
1711
+ case "TSTypeParameterInstantiation":
1712
+ case "TSTypePredicate":
1713
+ case "TSTypeQuery":
1714
+ case "TSTypeReference":
1715
+ case "TSUndefinedKeyword":
1716
+ case "TSUnionType":
1717
+ case "TSUnknownKeyword":
1718
+ case "TSVoidKeyword": printUnclassifiedNode(state, node, node.type);
1719
+ }
1720
+ }
1721
+ function printUnclassifiedNode(state, node, kind) {
1722
+ if (isTSType(node)) {
1723
+ printTSType(state, node);
1724
+ return;
1725
+ }
1726
+ printTypeHolderNode(state, node, kind);
1727
+ }
1728
+ function printTypeHolderNode(state, node, kind) {
1729
+ switch (kind) {
1730
+ case "TSTypeAnnotation":
1731
+ printTypeAnnotationHolder(state, node);
1732
+ break;
1733
+ case "TSTypeParameterDeclaration":
1734
+ printTypeParameterDeclarationHolder(state, node);
1735
+ break;
1736
+ case "TSTypeParameterInstantiation":
1737
+ printTypeParameterInstantiationHolder(state, node);
1738
+ break;
1739
+ case "TSTypeParameter":
1740
+ printTypeParameterHolder(state, node);
1741
+ break;
1742
+ default: state.out += `/* unknown:${kind} */`;
1743
+ }
1744
+ }
1745
+ function printTypeAnnotationHolder(state, node) {
1746
+ if (isNodeOfKind(node, "TSTypeAnnotation")) {
1747
+ state.out += ": ";
1748
+ printTSType(state, node.typeAnnotation);
1749
+ }
1750
+ }
1751
+ function printTypeParameterDeclarationHolder(state, node) {
1752
+ if (isNodeOfKind(node, "TSTypeParameterDeclaration")) printTSTypeParameterDeclaration(state, node);
1753
+ }
1754
+ function printTypeParameterInstantiationHolder(state, node) {
1755
+ if (isNodeOfKind(node, "TSTypeParameterInstantiation")) printTSTypeParameterInstantiation(state, node);
1756
+ }
1757
+ function printTypeParameterHolder(state, node) {
1758
+ if (isNodeOfKind(node, "TSTypeParameter")) printTSTypeParameter(state, node);
1759
+ }
1760
+ function printLiteral(state, node) {
1761
+ state.out += literalText(node);
1762
+ }
1763
+ function printIdentifier(state, node) {
1764
+ state.out += node.name;
1765
+ }
1766
+ function printArrayExpression(state, node) {
1767
+ state.out += `[${node.elements.map((element) => arrayElementText(state, element)).join(", ")}]`;
1768
+ }
1769
+ function arrayElementText(state, element) {
1770
+ if (element === null) return "";
1771
+ return assignmentNodeText(state, element);
1772
+ }
1773
+ function printObjectExpression(state, node) {
1774
+ switch (node.properties.length) {
1775
+ case 0:
1776
+ state.out += "{}";
1777
+ break;
1778
+ default: state.out += `{ ${nodeListText(state, node.properties, PREC.Sequence)} }`;
1779
+ }
1780
+ }
1781
+ function printProperty(state, node) {
1782
+ switch (propertyForm(node)) {
1783
+ case "accessor":
1784
+ state.out += `${node.kind} `;
1785
+ state.out += propertyKeyText(state, node.key, node.computed === true, PREC.Assignment);
1786
+ printFunctionValueTail(state, node.value);
1787
+ break;
1788
+ case "method":
1789
+ state.out += propertyKeyText(state, node.key, node.computed === true, PREC.Assignment);
1790
+ printFunctionValueTail(state, node.value);
1791
+ break;
1792
+ case "shorthand":
1793
+ state.out += identifierNameText(node.key);
1794
+ break;
1795
+ case "shorthandDefault":
1796
+ printShorthandDefaultProperty(state, node);
1797
+ break;
1798
+ default:
1799
+ state.out += propertyKeyText(state, node.key, node.computed === true, PREC.Assignment);
1800
+ state.out += ": ";
1801
+ printNodePrec(state, node.value, PREC.Assignment);
1802
+ }
1803
+ }
1804
+ function printFunctionValueTail(state, value) {
1805
+ if (isFunctionNode(value)) printFunctionTail(state, value);
1806
+ }
1807
+ function printShorthandDefaultProperty(state, node) {
1808
+ if (!isAssignmentPattern(node.value)) return;
1809
+ const right = assignmentNodeText(state, node.value.right);
1810
+ state.out += `${identifierNameText(node.key)} = ${right}`;
1811
+ }
1812
+ function propertyKeyText(state, key, computed, computedPrec) {
1813
+ if (computed) return `[${capture(state, () => printNodePrec(state, key, computedPrec))}]`;
1814
+ return plainPropertyKeyText(state, key);
1815
+ }
1816
+ function plainPropertyKeyText(state, key) {
1817
+ switch (nodeKind(key)) {
1818
+ case "Identifier": return identifierNameText(key);
1819
+ case "PrivateIdentifier": return privateIdentifierText(key);
1820
+ case "Literal": return literalCapture(state, key);
1821
+ default: return capture(state, () => printNodePrec(state, key, PREC.Assignment));
1822
+ }
1823
+ }
1824
+ function printFunctionTail(state, fn) {
1825
+ state.out += typeParametersText(state, fn.typeParameters);
1826
+ state.out += `(${paramsText(state, fn.params)})`;
1827
+ state.out += typeAnnotationText(state, fn.returnType);
1828
+ state.out += functionBodyText(state, fn);
1829
+ }
1830
+ function functionBodyText(state, fn) {
1831
+ const body = fn.body;
1832
+ if (body !== null) return ` ${capture(state, () => printBlockStatement(state, body))}`;
1833
+ return ";";
1834
+ }
1835
+ function paramsText(state, params) {
1836
+ return capture(state, () => printParams(state, params));
1837
+ }
1838
+ function typeParametersText(state, params) {
1839
+ if (params == null) return "";
1840
+ return capture(state, () => printTSTypeParameterDeclaration(state, params));
1841
+ }
1842
+ function typeArgumentsText(state, args) {
1843
+ if (args == null) return "";
1844
+ return capture(state, () => printTSTypeParameterInstantiation(state, args));
1845
+ }
1846
+ function typeAnnotationText(state, annotation) {
1847
+ if (annotation == null) return "";
1848
+ return capture(state, () => printTSTypeAnnotation(state, annotation));
1849
+ }
1850
+ function printTemplateLiteral(state, node) {
1851
+ state.out += `\`${node.quasis.map((quasi, index) => quasiText(state, quasi, node.expressions[index])).join("")}\``;
1852
+ }
1853
+ function quasiText(state, quasi, expression) {
1854
+ if (quasi.tail) return quasi.value.raw;
1855
+ return `${quasi.value.raw}\${${sequenceNodeText(state, expression)}}`;
1856
+ }
1857
+ function printTaggedTemplate(state, node) {
1858
+ printNodePrec(state, node.tag, PREC.Member);
1859
+ if (node.typeArguments != null) printTSTypeParameterInstantiation(state, node.typeArguments);
1860
+ printTemplateLiteral(state, node.quasi);
1861
+ }
1862
+ function printMemberExpression(state, node, _prec) {
1863
+ state.out += wrappedExpressionText(state, node.object, PREC.Member, MEMBER_OBJECT_WRAPPED_KINDS);
1864
+ state.out += flagText(node.optional, "?.");
1865
+ state.out += memberSelectorText(state, node);
1866
+ }
1867
+ function memberSelectorText(state, access) {
1868
+ if (access.computed) return `[${sequenceNodeText(state, access.property)}]`;
1869
+ return `${flagText(!access.optional, ".")}${memberPropertyText(state, access.property)}`;
1870
+ }
1871
+ function memberPropertyText(state, property) {
1872
+ switch (nodeKind(property)) {
1873
+ case "Identifier": return identifierNameText(property);
1874
+ case "PrivateIdentifier": return privateIdentifierText(property);
1875
+ default: return sequenceNodeText(state, property);
1876
+ }
1877
+ }
1878
+ function printCallExpression(state, node, _prec) {
1879
+ state.out += wrappedExpressionText(state, node.callee, PREC.Member, CALLEE_WRAPPED_KINDS);
1880
+ state.out += flagText(node.optional, "?.");
1881
+ state.out += typeArgumentsText(state, node.typeArguments);
1882
+ state.out += `(${nodeListText(state, node.arguments, PREC.Assignment)})`;
1883
+ }
1884
+ function printNewExpression(state, node, _prec) {
1885
+ state.out += "new ";
1886
+ state.out += printExpressionToString(state, node.callee, PREC.Member);
1887
+ state.out += typeArgumentsText(state, node.typeArguments);
1888
+ state.out += `(${nodeListText(state, node.arguments, PREC.Assignment)})`;
1889
+ }
1890
+ function printMetaProperty(state, node) {
1891
+ state.out += `${node.meta.name}.${node.property.name}`;
1892
+ }
1893
+ function printV8Intrinsic(state, node) {
1894
+ state.out += `%${node.name.name}(${nodeListText(state, node.arguments, PREC.Assignment)})`;
1895
+ }
1896
+ function printImportExpression(state, node) {
1897
+ state.out += `import${flagText(node.phase, `.${node.phase}`)}(`;
1898
+ state.out += assignmentNodeText(state, node.source);
1899
+ state.out += flagText(node.options, `, ${assignmentNodeText(state, node.options)}`);
1900
+ state.out += ")";
1901
+ }
1902
+ function printUpdateExpression(state, node, _prec) {
1903
+ const operand = wrappedExpressionText(state, node.argument, PREC.Update, MEMBER_OBJECT_WRAPPED_KINDS);
1904
+ if (node.prefix) {
1905
+ state.out += `${node.operator}${operand}`;
1906
+ return;
1907
+ }
1908
+ state.out += `${operand}${node.operator}`;
1909
+ }
1910
+ function printUnaryExpression(state, node, _prec) {
1911
+ state.out += node.operator;
1912
+ state.out += flagText(UNARY_WORD_OPERATORS[node.operator] === true, " ");
1913
+ state.out += wrappedExpressionText(state, node.argument, PREC.Unary, UNARY_OPERAND_WRAPPED_KINDS);
1914
+ }
1915
+ function printBinaryExpression(state, node, prec) {
1916
+ const myPrec = binaryPrec(node.operator);
1917
+ const leftStr = wrapIfNeeded(state, node.left, precOf(node.left), myPrec, false, node.operator);
1918
+ const rightStr = wrapIfNeeded(state, node.right, precOf(node.right), myPrec, true, node.operator);
1919
+ const whole = `${leftStr} ${node.operator} ${rightStr}`;
1920
+ if (myPrec < prec) state.out += `(${whole})`;
1921
+ else state.out += whole;
1922
+ }
1923
+ function printLogicalExpression(state, node, prec) {
1924
+ const myPrec = logicalPrec(node.operator);
1925
+ const leftStr = wrapIfNeeded(state, node.left, precOf(node.left), myPrec, false, node.operator);
1926
+ const rightStr = wrapIfNeeded(state, node.right, precOf(node.right), myPrec, true, node.operator);
1927
+ const whole = `${leftStr} ${node.operator} ${rightStr}`;
1928
+ if (myPrec < prec) state.out += `(${whole})`;
1929
+ else state.out += whole;
1930
+ }
1931
+ function printConditionalExpression(state, node, prec) {
1932
+ const myPrec = PREC.Conditional;
1933
+ const whole = `${wrapIfNeeded(state, node.test, precOf(node.test), myPrec, false)} ? ${printExpressionToString(state, node.consequent, PREC.Assignment)} : ${printExpressionToString(state, node.alternate, PREC.Assignment)}`;
1934
+ if (myPrec < prec) state.out += `(${whole})`;
1935
+ else state.out += whole;
1936
+ }
1937
+ function printAssignmentExpression(state, node, prec) {
1938
+ const myPrec = PREC.Assignment;
1939
+ const leftStr = printExpressionToString(state, node.left, myPrec);
1940
+ const rightStr = printExpressionToString(state, node.right, myPrec - .1);
1941
+ const whole = `${leftStr} ${node.operator} ${rightStr}`;
1942
+ if (myPrec < prec) state.out += `(${whole})`;
1943
+ else state.out += whole;
1944
+ }
1945
+ function printAssignmentPattern(state, node, prec) {
1946
+ const leftText = printExpressionToString(state, node.left, PREC.Assignment) + typeAnnotationText(state, bindingTypeAnnotation(node.left));
1947
+ const rightText = printExpressionToString(state, node.right, PREC.Assignment);
1948
+ state.out += parenthesizedIf(PREC.Assignment < prec, `${leftText} = ${rightText}`);
1949
+ }
1950
+ function printObjectPattern(state, node) {
1951
+ switch (node.properties.length) {
1952
+ case 0:
1953
+ state.out += "{}";
1954
+ break;
1955
+ default: state.out += `{ ${nodeListText(state, node.properties, PREC.Sequence)} }`;
1956
+ }
1957
+ }
1958
+ function printArrayPattern(state, node) {
1959
+ state.out += `[${node.elements.map((element) => arrayElementText(state, element)).join(", ")}]`;
1960
+ }
1961
+ function printSequenceExpression(state, node, prec) {
1962
+ const whole = node.expressions.map((expression) => printExpressionToString(state, expression, PREC.Sequence)).join(", ");
1963
+ state.out += parenthesizedIf(PREC.Sequence < prec, whole);
1964
+ }
1965
+ function printYieldExpression(state, node, _prec) {
1966
+ if (node.delegate) state.out += "yield*";
1967
+ else state.out += "yield";
1968
+ state.out += flagText(node.argument, ` ${assignmentNodeText(state, node.argument)}`);
1969
+ }
1970
+ function printArrowFunction(state, node, prec) {
1971
+ const arrow = `${flagText(node.async, "async ")}${typeParametersText(state, node.typeParameters)}${arrowParamsText(state, node)}${typeAnnotationText(state, node.returnType)} => ${arrowBodyText(state, node)}`;
1972
+ state.out += parenthesizedIf(PREC.Assignment < prec, arrow);
1973
+ }
1974
+ function arrowParamsText(state, node) {
1975
+ const bareParam = bareArrowParamName(node);
1976
+ if (bareParam.length === 0) return `(${paramsText(state, node.params)})`;
1977
+ return bareParam;
1978
+ }
1979
+ function arrowBodyText(state, node) {
1980
+ const body = node.body;
1981
+ if (arrowBodyIsBlock(body)) return capture(state, () => printBlockStatement(state, body));
1982
+ return assignmentNodeText(state, body);
1983
+ }
1984
+ function printFunction(state, node, _prec) {
1985
+ state.out += functionHeaderText(node);
1986
+ printFunctionTail(state, node);
1987
+ }
1988
+ function printClass(state, node, _prec) {
1989
+ state.out += capture(state, () => printDecorators(state, node.decorators));
1990
+ state.out += `${flagText(node.declare, "declare ")}${flagText(node.abstract, "abstract ")}class${namedDeclarationText(node)}`;
1991
+ state.out += typeParametersText(state, node.typeParameters);
1992
+ state.out += classHeritageText(state, node);
1993
+ state.out += classImplementsText(state, node);
1994
+ state.out += " ";
1995
+ printClassBody(state, node.body);
1996
+ }
1997
+ function classHeritageText(state, node) {
1998
+ if (node.superClass !== null) return ` extends ${assignmentNodeText(state, node.superClass)}${typeArgumentsText(state, node.superTypeArguments)}`;
1999
+ return "";
2000
+ }
2001
+ function classImplementsText(state, node) {
2002
+ const rendered = (node.implements ?? []).map((heritage) => heritageText(state, heritage)).join(", ");
2003
+ return flagText(rendered, ` implements ${rendered}`);
2004
+ }
2005
+ function heritageText(state, heritage) {
2006
+ return `${assignmentNodeText(state, heritage.expression)}${typeArgumentsText(state, heritage.typeArguments)}`;
2007
+ }
2008
+ function printDecorators(state, decorators) {
2009
+ const rendered = (decorators ?? []).map((decorator) => decoratorText(state, decorator)).join(" ");
2010
+ state.out += flagText(rendered, `${rendered} `);
2011
+ }
2012
+ function decoratorText(state, decorator) {
2013
+ return `@${capture(state, () => printNodePrec(state, decorator.expression, PREC.Member))}`;
2014
+ }
2015
+ function printJSXElement(state, node) {
2016
+ printJSXOpeningElement(state, node.openingElement);
2017
+ node.children.forEach((child) => printJSXChild(state, child));
2018
+ printJSXClosingElement(state, node);
2019
+ }
2020
+ function printJSXClosingElement(state, node) {
2021
+ if (node.closingElement === null) return;
2022
+ state.out += `</${jsxElementNameText(state, node.closingElement.name)}>`;
2023
+ }
2024
+ function printJSXFragment(state, node) {
2025
+ state.out += "<>";
2026
+ for (const child of node.children) printJSXChild(state, child);
2027
+ state.out += "</>";
2028
+ }
2029
+ function printJSXOpeningElement(state, node) {
2030
+ state.out += `<${jsxElementNameText(state, node.name)}`;
2031
+ state.out += typeArgumentsText(state, node.typeArguments);
2032
+ state.out += node.attributes.map((attribute) => ` ${sequenceNodeText(state, attribute)}`).join("");
2033
+ if (node.selfClosing) {
2034
+ state.out += " />";
2035
+ return;
1275
2036
  }
1276
- nodeListText(nodes, prec) {
1277
- return nodes.map((node) => this.capture(() => this.printNode(node, prec))).join(", ");
2037
+ state.out += ">";
2038
+ }
2039
+ function jsxElementNameText(state, name) {
2040
+ switch (name.type) {
2041
+ case "JSXIdentifier": return name.name;
2042
+ case "JSXNamespacedName": return `${name.namespace.name}:${name.name.name}`;
2043
+ case "JSXMemberExpression": return capture(state, () => printJSXMemberExpression(state, name));
1278
2044
  }
1279
- wrappedExpressionText(node, prec, wrappedKinds) {
1280
- const printed = this.printExpressionToString(node, prec);
1281
- switch (wrappedKinds[node.type] === true) {
1282
- case true: return `(${printed})`;
1283
- default: return printed;
1284
- }
2045
+ }
2046
+ function printJSXMemberExpression(state, node) {
2047
+ const obj = node.object;
2048
+ if (obj.type === "JSXIdentifier") {
2049
+ state.out += `${obj.name}.${node.property.name}`;
2050
+ return;
1285
2051
  }
1286
- printNode(node, prec) {
1287
- const kind = nodeKind(node);
1288
- switch (kind) {
1289
- case ABSENT_NODE_KIND: return;
1290
- case "Literal":
1291
- this.printLiteral(node);
1292
- break;
1293
- case "Identifier":
1294
- this.printIdentifier(node);
1295
- break;
1296
- case "PrivateIdentifier":
1297
- this.out += `#${node.name}`;
1298
- break;
1299
- case "ThisExpression":
1300
- this.out += "this";
1301
- break;
1302
- case "Super":
1303
- this.out += "super";
1304
- break;
1305
- case "ArrayExpression":
1306
- this.printArrayExpression(node);
1307
- break;
1308
- case "ObjectExpression":
1309
- this.printObjectExpression(node);
1310
- break;
1311
- case "Property":
1312
- this.printProperty(node);
1313
- break;
1314
- case "TemplateLiteral":
1315
- this.printTemplateLiteral(node);
1316
- break;
1317
- case "TemplateElement":
1318
- this.out += node.value.raw;
1319
- break;
1320
- case "TaggedTemplateExpression":
1321
- this.printTaggedTemplate(node);
1322
- break;
1323
- case "MemberExpression":
1324
- this.printMemberExpression(node, prec);
1325
- break;
1326
- case "CallExpression":
1327
- this.printCallExpression(node, prec);
1328
- break;
1329
- case "NewExpression":
1330
- this.printNewExpression(node, prec);
1331
- break;
1332
- case "MetaProperty":
1333
- this.printMetaProperty(node);
1334
- break;
1335
- case "SpreadElement":
1336
- this.out += "...";
1337
- this.printNode(node.argument, PREC.Assignment);
1338
- break;
1339
- case "RestElement":
1340
- this.out += "...";
1341
- this.printNode(node.argument, PREC.Assignment);
1342
- break;
1343
- case "UpdateExpression":
1344
- this.printUpdateExpression(node, prec);
1345
- break;
1346
- case "UnaryExpression":
1347
- this.printUnaryExpression(node, prec);
1348
- break;
1349
- case "BinaryExpression":
1350
- this.printBinaryExpression(node, prec);
1351
- break;
1352
- case "LogicalExpression":
1353
- this.printLogicalExpression(node, prec);
1354
- break;
1355
- case "ConditionalExpression":
1356
- this.printConditionalExpression(node, prec);
1357
- break;
1358
- case "AssignmentExpression":
1359
- this.printAssignmentExpression(node, prec);
1360
- break;
1361
- case "AssignmentPattern":
1362
- this.printAssignmentPattern(node, prec);
1363
- break;
1364
- case "ObjectPattern":
1365
- this.printObjectPattern(node);
1366
- break;
1367
- case "ArrayPattern":
1368
- this.printArrayPattern(node);
1369
- break;
1370
- case "SequenceExpression":
1371
- this.printSequenceExpression(node, prec);
1372
- break;
1373
- case "AwaitExpression":
1374
- this.out += "await ";
1375
- this.printNode(node.argument, PREC.Unary);
1376
- break;
1377
- case "YieldExpression":
1378
- this.printYieldExpression(node, prec);
1379
- break;
1380
- case "ChainExpression":
1381
- this.printNode(node.expression, prec);
1382
- break;
1383
- case "ParenthesizedExpression":
1384
- this.out += "(";
1385
- this.printNode(node.expression, PREC.Sequence);
1386
- this.out += ")";
1387
- break;
1388
- case "ImportExpression":
1389
- this.printImportExpression(node);
1390
- break;
1391
- case "V8IntrinsicExpression":
1392
- this.printV8Intrinsic(node);
1393
- break;
1394
- case "ArrowFunctionExpression":
1395
- this.printArrowFunction(node, prec);
1396
- break;
1397
- case "FunctionExpression":
1398
- case "FunctionDeclaration":
1399
- case "TSDeclareFunction":
1400
- case "TSEmptyBodyFunctionExpression":
1401
- this.printFunction(node, prec);
1402
- break;
1403
- case "ClassDeclaration":
1404
- case "ClassExpression":
1405
- this.printClass(node, prec);
1406
- break;
1407
- case "JSXElement":
1408
- this.printJSXElement(node);
1409
- break;
1410
- case "JSXFragment":
1411
- this.printJSXFragment(node);
1412
- break;
1413
- case "JSXOpeningElement":
1414
- this.printJSXOpeningElement(node);
1415
- break;
1416
- case "JSXClosingElement": break;
1417
- case "JSXIdentifier":
1418
- this.out += node.name;
1419
- break;
1420
- case "JSXNamespacedName":
1421
- this.out += `${node.namespace.name}:${node.name.name}`;
1422
- break;
1423
- case "JSXMemberExpression":
1424
- this.printJSXMemberExpression(node);
1425
- break;
1426
- case "JSXAttribute":
1427
- this.printJSXAttribute(node);
1428
- break;
1429
- case "JSXSpreadAttribute":
1430
- this.out += "{...";
1431
- this.printNode(node.argument, PREC.Assignment);
1432
- this.out += "}";
1433
- break;
1434
- case "JSXExpressionContainer":
1435
- this.out += "{";
1436
- this.printNode(node.expression, PREC.Sequence);
1437
- this.out += "}";
1438
- break;
1439
- case "JSXEmptyExpression": break;
1440
- case "JSXText":
1441
- this.out += node.value;
1442
- break;
1443
- case "JSXSpreadChild":
1444
- this.out += "{...";
1445
- this.printNode(node.expression, PREC.Assignment);
1446
- this.out += "}";
1447
- break;
1448
- case "TSAsExpression":
1449
- this.printTSAsExpression(node, prec);
1450
- break;
1451
- case "TSSatisfiesExpression":
1452
- this.printTSSatisfiesExpression(node, prec);
1453
- break;
1454
- case "TSTypeAssertion":
1455
- this.printTSTypeAssertion(node, prec);
1456
- break;
1457
- case "TSNonNullExpression":
1458
- this.printNode(node.expression, PREC.Member);
1459
- this.out += "!";
1460
- break;
1461
- case "TSInstantiationExpression":
1462
- this.printTSInstantiationExpression(node, prec);
1463
- break;
1464
- case "BlockStatement":
1465
- this.printBlockStatement(node);
1466
- break;
1467
- case "EmptyStatement":
1468
- this.out += ";";
1469
- break;
1470
- case "ExpressionStatement":
1471
- this.printExpressionStatement(node);
1472
- break;
1473
- case "IfStatement":
1474
- this.printIfStatement(node);
1475
- break;
1476
- case "DoWhileStatement":
1477
- this.printDoWhileStatement(node);
1478
- break;
1479
- case "WhileStatement":
1480
- this.printWhileStatement(node);
1481
- break;
1482
- case "ForStatement":
1483
- this.printForStatement(node);
1484
- break;
1485
- case "ForInStatement":
1486
- this.printForInStatement(node);
1487
- break;
1488
- case "ForOfStatement":
1489
- this.printForOfStatement(node);
1490
- break;
1491
- case "ContinueStatement":
1492
- this.printJumpStatement("continue", node.label);
1493
- break;
1494
- case "BreakStatement":
1495
- this.printJumpStatement("break", node.label);
1496
- break;
1497
- case "ReturnStatement":
1498
- this.printReturnStatement(node);
1499
- break;
1500
- case "WithStatement":
1501
- this.printWithStatement(node);
1502
- break;
1503
- case "SwitchStatement":
1504
- this.printSwitchStatement(node);
1505
- break;
1506
- case "SwitchCase": break;
1507
- case "LabeledStatement":
1508
- this.printLabeledStatement(node);
1509
- break;
1510
- case "ThrowStatement":
1511
- this.out += "throw ";
1512
- this.printNode(node.argument, PREC.Sequence);
1513
- this.out += ";";
1514
- break;
1515
- case "TryStatement":
1516
- this.printTryStatement(node);
1517
- break;
1518
- case "CatchClause": break;
1519
- case "DebuggerStatement":
1520
- this.out += "debugger;";
1521
- break;
1522
- case "VariableDeclaration":
1523
- this.printVariableDeclaration(node);
1524
- break;
1525
- case "VariableDeclarator":
1526
- this.printVariableDeclarator(node);
1527
- break;
1528
- case "ClassBody":
1529
- this.printClassBody(node);
1530
- break;
1531
- case "MethodDefinition":
1532
- case "TSAbstractMethodDefinition":
1533
- this.printMethodDefinition(node);
1534
- break;
1535
- case "PropertyDefinition":
1536
- case "TSAbstractPropertyDefinition":
1537
- this.printPropertyDefinition(node);
1538
- break;
1539
- case "AccessorProperty":
1540
- case "TSAbstractAccessorProperty":
1541
- this.printAccessorProperty(node);
1542
- break;
1543
- case "StaticBlock":
1544
- this.printStaticBlock(node);
1545
- break;
1546
- case "ImportDeclaration":
1547
- this.printImportDeclaration(node);
1548
- break;
1549
- case "ExportNamedDeclaration":
1550
- this.printExportNamedDeclaration(node);
1551
- break;
1552
- case "ExportDefaultDeclaration":
1553
- this.printExportDefaultDeclaration(node);
1554
- break;
1555
- case "ExportAllDeclaration":
1556
- this.printExportAllDeclaration(node);
1557
- break;
1558
- case "Decorator":
1559
- this.out += "@";
1560
- this.printNode(node.expression, PREC.Member);
1561
- break;
1562
- case "TSTypeAliasDeclaration":
1563
- this.printTSTypeAliasDeclaration(node);
1564
- break;
1565
- case "TSInterfaceDeclaration":
1566
- this.printTSInterfaceDeclaration(node);
1567
- break;
1568
- case "TSEnumDeclaration":
1569
- this.printTSEnumDeclaration(node);
1570
- break;
1571
- case "TSModuleDeclaration":
1572
- this.printTSModuleDeclaration(node);
1573
- break;
1574
- case "TSImportEqualsDeclaration":
1575
- this.printTSImportEqualsDeclaration(node);
1576
- break;
1577
- case "TSExportAssignment":
1578
- this.out += `export = `;
1579
- this.printNode(node.expression, PREC.Sequence);
1580
- this.out += ";";
1581
- break;
1582
- case "TSNamespaceExportDeclaration":
1583
- this.out += `export as namespace ${node.id.name};`;
1584
- break;
1585
- default: this.printUnclassifiedNode(node, kind);
1586
- }
2052
+ printJSXMemberExpression(state, obj);
2053
+ state.out += `.${node.property.name}`;
2054
+ }
2055
+ function printJSXAttribute(state, node) {
2056
+ state.out += jsxAttributeNameText(node.name);
2057
+ state.out += jsxAttributeValueClauseText(state, node.value);
2058
+ }
2059
+ function jsxAttributeValueClauseText(state, value) {
2060
+ if (value === null) return "";
2061
+ return `=${jsxAttributeValueText(state, value)}`;
2062
+ }
2063
+ function jsxAttributeValueText(state, value) {
2064
+ switch (value.type) {
2065
+ case "Literal": return capture(state, () => printLiteral(state, value));
2066
+ case "JSXExpressionContainer": return `{${sequenceNodeText(state, value.expression)}}`;
2067
+ case "JSXElement":
2068
+ case "JSXFragment": return sequenceNodeText(state, value);
1587
2069
  }
1588
- /** TS type nodes and the wrappers that carry them, which oxc kinds apart from expressions. */
1589
- printUnclassifiedNode(node, kind) {
1590
- if (isTSTypeNode(kind)) {
1591
- this.printTSType(node);
2070
+ }
2071
+ function printJSXChild(state, child) {
2072
+ switch (child.type) {
2073
+ case "JSXText":
2074
+ state.out += child.value;
1592
2075
  return;
1593
- }
1594
- this.printTypeHolderNode(node, kind);
1595
- }
1596
- printTypeHolderNode(node, kind) {
1597
- switch (kind) {
1598
- case "TSTypeAnnotation":
1599
- this.out += ": ";
1600
- this.printTSType(node.typeAnnotation);
1601
- break;
1602
- case "TSTypeParameterDeclaration":
1603
- this.printTSTypeParameterDeclaration(node);
1604
- break;
1605
- case "TSTypeParameterInstantiation":
1606
- this.printTSTypeParameterInstantiation(node);
1607
- break;
1608
- case "TSTypeParameter":
1609
- this.printTSTypeParameter(node);
1610
- break;
1611
- default: this.out += `/* unknown:${kind} */`;
1612
- }
1613
- }
1614
- printLiteral(node) {
1615
- this.out += literalText(node);
1616
- }
1617
- printIdentifier(node) {
1618
- this.out += node.name;
1619
- }
1620
- printArrayExpression(node) {
1621
- this.out += `[${node.elements.map((element) => this.arrayElementText(element)).join(", ")}]`;
1622
- }
1623
- arrayElementText(element) {
1624
- switch (element === null) {
1625
- case true: return "";
1626
- default: return this.assignmentNodeText(element);
1627
- }
1628
- }
1629
- printObjectExpression(node) {
1630
- switch (node.properties.length) {
1631
- case 0:
1632
- this.out += "{}";
1633
- break;
1634
- default: this.out += `{ ${this.nodeListText(node.properties, PREC.Sequence)} }`;
1635
- }
1636
- }
1637
- printProperty(node) {
1638
- const fields = node;
1639
- switch (propertyForm(fields)) {
1640
- case "accessor":
1641
- this.out += `${fields.kind} `;
1642
- this.out += this.propertyKeyText(fields.key, fields.computed === true, PREC.Assignment);
1643
- this.printFunctionTail(fields.value);
1644
- break;
1645
- case "method":
1646
- this.out += `${flagText(fields.async, "async ")}${flagText(fields.generator, "*")}`;
1647
- this.out += this.propertyKeyText(fields.key, fields.computed === true, PREC.Assignment);
1648
- this.printFunctionTail(fields.value);
1649
- break;
1650
- case "shorthand":
1651
- this.out += identifierName(fields.key);
1652
- break;
1653
- case "shorthandDefault":
1654
- this.printShorthandDefaultProperty(fields);
1655
- break;
1656
- default:
1657
- this.out += this.propertyKeyText(fields.key, fields.computed === true, PREC.Assignment);
1658
- this.out += ": ";
1659
- this.printNode(fields.value, PREC.Assignment);
1660
- }
1661
- }
1662
- printShorthandDefaultProperty(fields) {
1663
- const right = this.assignmentNodeText(fields.value.right);
1664
- this.out += `${identifierName(fields.key)} = ${right}`;
1665
- }
1666
- propertyKeyText(key, computed, computedPrec) {
1667
- switch (computed) {
1668
- case true: return `[${this.capture(() => this.printNode(key, computedPrec))}]`;
1669
- default: return this.plainPropertyKeyText(key);
1670
- }
1671
- }
1672
- plainPropertyKeyText(key) {
1673
- switch (key.type) {
1674
- case "Identifier": return key.name;
1675
- case "PrivateIdentifier": return `#${key.name}`;
1676
- case "Literal": return this.capture(() => this.printLiteral(key));
1677
- default: return this.capture(() => this.printNode(key, PREC.Assignment));
1678
- }
1679
- }
1680
- printPropertyKeyForClass(key, computed) {
1681
- this.out += this.propertyKeyText(key, computed, PREC.Sequence);
1682
- }
1683
- printFunctionTail(fn) {
1684
- this.out += this.typeParametersText(fn.typeParameters);
1685
- this.out += `(${this.paramsText(fn.params)})`;
1686
- this.out += this.typeAnnotationText(fn.returnType);
1687
- this.out += this.functionBodyText(fn);
1688
- }
1689
- functionBodyText(fn) {
1690
- switch (Boolean(fn.body)) {
1691
- case true: return ` ${this.capture(() => this.printBlockStatement(fn.body))}`;
1692
- default: return ";";
1693
- }
1694
- }
1695
- paramsText(params) {
1696
- return this.capture(() => this.printParams(params));
1697
- }
1698
- typeParametersText(params) {
1699
- switch (Boolean(params)) {
1700
- case true: return this.capture(() => this.printTSTypeParameterDeclaration(params));
1701
- default: return "";
1702
- }
1703
- }
1704
- typeArgumentsText(args) {
1705
- switch (Boolean(args)) {
1706
- case true: return this.capture(() => this.printTSTypeParameterInstantiation(args));
1707
- default: return "";
1708
- }
1709
- }
1710
- typeAnnotationText(annotation) {
1711
- switch (Boolean(annotation)) {
1712
- case true: return this.capture(() => this.printTSTypeAnnotation(annotation));
1713
- default: return "";
1714
- }
1715
- }
1716
- printTemplateLiteral(node) {
1717
- this.out += `\`${node.quasis.map((quasi, index) => this.quasiText(quasi, node.expressions[index])).join("")}\``;
1718
- }
1719
- quasiText(quasi, expression) {
1720
- switch (quasi.tail) {
1721
- case true: return quasi.value.raw;
1722
- default: return `${quasi.value.raw}\${${this.sequenceNodeText(expression)}}`;
1723
- }
1724
- }
1725
- printTaggedTemplate(node) {
1726
- this.printNode(node.tag, PREC.Member);
1727
- if (node.typeArguments) this.printTSTypeParameterInstantiation(node.typeArguments);
1728
- this.printTemplateLiteral(node.quasi);
1729
- }
1730
- printMemberExpression(node, _prec) {
1731
- const access = node;
1732
- this.out += this.wrappedExpressionText(access.object, PREC.Member, MEMBER_OBJECT_WRAPPED_KINDS);
1733
- this.out += flagText(access.optional, "?.");
1734
- this.out += this.memberSelectorText(access);
1735
- }
1736
- memberSelectorText(access) {
1737
- switch (access.computed) {
1738
- case true: return `[${this.sequenceNodeText(access.property)}]`;
1739
- default: return `${flagText(!access.optional, ".")}${this.memberPropertyText(access.property)}`;
1740
- }
1741
- }
1742
- memberPropertyText(property) {
1743
- switch (property.type) {
1744
- case "Identifier": return property.name;
1745
- case "PrivateIdentifier": return `#${property.name}`;
1746
- default: return this.sequenceNodeText(property);
1747
- }
1748
- }
1749
- printCallExpression(node, _prec) {
1750
- this.out += this.wrappedExpressionText(node.callee, PREC.Member, CALLEE_WRAPPED_KINDS);
1751
- this.out += flagText(node.optional, "?.");
1752
- this.out += this.typeArgumentsText(node.typeArguments);
1753
- this.out += `(${this.nodeListText(node.arguments, PREC.Assignment)})`;
1754
- }
1755
- printNewExpression(node, _prec) {
1756
- this.out += "new ";
1757
- this.out += this.printExpressionToString(node.callee, PREC.Member);
1758
- this.out += this.typeArgumentsText(node.typeArguments);
1759
- this.out += `(${this.nodeListText(node.arguments, PREC.Assignment)})`;
1760
- }
1761
- printMetaProperty(node) {
1762
- this.out += `${node.meta.name}.${node.property.name}`;
1763
- }
1764
- printV8Intrinsic(node) {
1765
- this.out += `%${node.name.name}(${this.nodeListText(node.arguments, PREC.Assignment)})`;
1766
- }
1767
- printImportExpression(node) {
1768
- this.out += `import${flagText(node.phase, `.${node.phase}`)}(`;
1769
- this.out += this.assignmentNodeText(node.source);
1770
- this.out += flagText(node.options, `, ${this.assignmentNodeText(node.options)}`);
1771
- this.out += ")";
1772
- }
1773
- printUpdateExpression(node, _prec) {
1774
- const operand = this.wrappedExpressionText(node.argument, PREC.Update, MEMBER_OBJECT_WRAPPED_KINDS);
1775
- switch (node.prefix) {
1776
- case true:
1777
- this.out += `${node.operator}${operand}`;
1778
- break;
1779
- default: this.out += `${operand}${node.operator}`;
1780
- }
1781
- }
1782
- printUnaryExpression(node, _prec) {
1783
- this.out += node.operator;
1784
- this.out += flagText(UNARY_WORD_OPERATORS[node.operator] === true, " ");
1785
- this.out += this.wrappedExpressionText(node.argument, PREC.Unary, UNARY_OPERAND_WRAPPED_KINDS);
1786
- }
1787
- printBinaryExpression(node, prec) {
1788
- const myPrec = binaryPrec(node.operator);
1789
- const leftStr = this.wrapIfNeeded(node.left, precOf(node.left), myPrec, false, node.operator);
1790
- const rightStr = this.wrapIfNeeded(node.right, precOf(node.right), myPrec, true, node.operator);
1791
- const whole = `${leftStr} ${node.operator} ${rightStr}`;
1792
- if (myPrec < prec) this.out += `(${whole})`;
1793
- else this.out += whole;
1794
- }
1795
- printLogicalExpression(node, prec) {
1796
- const myPrec = logicalPrec(node.operator);
1797
- const leftStr = this.wrapIfNeeded(node.left, precOf(node.left), myPrec, false, node.operator);
1798
- const rightStr = this.wrapIfNeeded(node.right, precOf(node.right), myPrec, true, node.operator);
1799
- const whole = `${leftStr} ${node.operator} ${rightStr}`;
1800
- if (myPrec < prec) this.out += `(${whole})`;
1801
- else this.out += whole;
1802
- }
1803
- printConditionalExpression(node, prec) {
1804
- const myPrec = PREC.Conditional;
1805
- const whole = `${this.wrapIfNeeded(node.test, precOf(node.test), myPrec, false)} ? ${this.printExpressionToString(node.consequent, PREC.Assignment)} : ${this.printExpressionToString(node.alternate, PREC.Assignment)}`;
1806
- if (myPrec < prec) this.out += `(${whole})`;
1807
- else this.out += whole;
1808
- }
1809
- printAssignmentExpression(node, prec) {
1810
- const myPrec = PREC.Assignment;
1811
- const leftStr = this.printExpressionToString(node.left, myPrec);
1812
- const rightStr = this.printExpressionToString(node.right, myPrec - .1);
1813
- const whole = `${leftStr} ${node.operator} ${rightStr}`;
1814
- if (myPrec < prec) this.out += `(${whole})`;
1815
- else this.out += whole;
1816
- }
1817
- printAssignmentPattern(node, prec) {
1818
- const left = node.left;
1819
- const leftText = this.printExpressionToString(node.left, PREC.Assignment) + this.typeAnnotationText(left.typeAnnotation);
1820
- const rightText = this.printExpressionToString(node.right, PREC.Assignment);
1821
- this.out += parenthesizedIf(PREC.Assignment < prec, `${leftText} = ${rightText}`);
1822
- }
1823
- printObjectPattern(node) {
1824
- switch (node.properties.length) {
1825
- case 0:
1826
- this.out += "{}";
1827
- break;
1828
- default: this.out += `{ ${this.nodeListText(node.properties, PREC.Sequence)} }`;
1829
- }
1830
- }
1831
- printArrayPattern(node) {
1832
- this.out += `[${node.elements.map((element) => this.arrayElementText(element)).join(", ")}]`;
1833
- }
1834
- printSequenceExpression(node, prec) {
1835
- const whole = node.expressions.map((expression) => this.printExpressionToString(expression, PREC.Sequence)).join(", ");
1836
- this.out += parenthesizedIf(PREC.Sequence < prec, whole);
1837
- }
1838
- printYieldExpression(node, _prec) {
1839
- switch (Boolean(node.delegate)) {
1840
- case true:
1841
- this.out += "yield*";
1842
- break;
1843
- default: this.out += "yield";
1844
- }
1845
- this.out += flagText(node.argument, ` ${this.assignmentNodeText(node.argument)}`);
1846
- }
1847
- printArrowFunction(node, prec) {
1848
- const arrow = `${flagText(node.async, "async ")}${this.typeParametersText(node.typeParameters)}${this.arrowParamsText(node)}${this.typeAnnotationText(node.returnType)} => ${this.arrowBodyText(node)}`;
1849
- this.out += parenthesizedIf(PREC.Assignment < prec, arrow);
1850
- }
1851
- arrowParamsText(node) {
1852
- const bareParam = bareArrowParamName(node);
1853
- switch (bareParam.length) {
1854
- case 0: return `(${this.paramsText(node.params)})`;
1855
- default: return bareParam;
1856
- }
1857
- }
1858
- arrowBodyText(node) {
1859
- switch (arrowBodyIsBlock(node.body)) {
1860
- case true: return this.capture(() => this.printBlockStatement(node.body));
1861
- default: return this.assignmentNodeText(node.body);
1862
- }
1863
- }
1864
- printFunction(node, _prec) {
1865
- this.out += functionHeaderText(node);
1866
- this.printFunctionTail(node);
1867
- }
1868
- printClass(node, _prec) {
1869
- this.out += this.capture(() => this.printDecorators(node.decorators));
1870
- this.out += `${flagText(node.declare, "declare ")}${flagText(node.abstract, "abstract ")}class${namedDeclarationText(node)}`;
1871
- this.out += this.typeParametersText(node.typeParameters);
1872
- this.out += this.classHeritageText(node);
1873
- this.out += this.classImplementsText(node);
1874
- this.out += " ";
1875
- this.printClassBody(node.body);
1876
- }
1877
- classHeritageText(node) {
1878
- switch (Boolean(node.superClass)) {
1879
- case true: return ` extends ${this.assignmentNodeText(node.superClass)}${this.typeArgumentsText(node.superTypeArguments)}`;
1880
- default: return "";
1881
- }
1882
- }
1883
- classImplementsText(node) {
1884
- const rendered = (node.implements ?? []).map((heritage) => this.heritageText(heritage)).join(", ");
1885
- return flagText(rendered, ` implements ${rendered}`);
1886
- }
1887
- heritageText(heritage) {
1888
- return `${this.assignmentNodeText(heritage.expression)}${this.typeArgumentsText(heritage.typeArguments)}`;
1889
- }
1890
- printDecorators(decorators) {
1891
- const rendered = (decorators ?? []).map((decorator) => this.decoratorText(decorator)).join(" ");
1892
- this.out += flagText(rendered, `${rendered} `);
1893
- }
1894
- decoratorText(decorator) {
1895
- return `@${this.capture(() => this.printNode(decorator.expression, PREC.Member))}`;
1896
- }
1897
- printJSXElement(node) {
1898
- this.printJSXOpeningElement(node.openingElement);
1899
- node.children.forEach((child) => this.printJSXChild(child));
1900
- this.printJSXClosingElement(node);
1901
- }
1902
- printJSXClosingElement(node) {
1903
- if (!node.closingElement) return;
1904
- this.out += `</${this.jsxElementNameText(node.closingElement.name)}>`;
1905
- }
1906
- printJSXFragment(node) {
1907
- this.out += "<>";
1908
- for (const child of node.children) this.printJSXChild(child);
1909
- this.out += "</>";
1910
- }
1911
- printJSXOpeningElement(node) {
1912
- this.out += `<${this.jsxElementNameText(node.name)}`;
1913
- this.out += this.typeArgumentsText(node.typeArguments);
1914
- this.out += node.attributes.map((attribute) => ` ${this.sequenceNodeText(attribute)}`).join("");
1915
- switch (node.selfClosing) {
1916
- case true:
1917
- this.out += " />";
1918
- break;
1919
- default: this.out += ">";
1920
- }
1921
- }
1922
- jsxElementNameText(name) {
1923
- switch (name.type) {
1924
- case "JSXIdentifier": return name.name;
1925
- case "JSXNamespacedName": return `${name.namespace.name}:${name.name.name}`;
1926
- default: return this.capture(() => this.printJSXMemberExpression(name));
1927
- }
1928
- }
1929
- printJSXMemberExpression(node) {
1930
- const obj = node.object;
1931
- if (obj.type === "JSXIdentifier") this.out += `${obj.name}.${node.property.name}`;
1932
- else {
1933
- this.printJSXMemberExpression(obj);
1934
- this.out += `.${node.property.name}`;
1935
- }
1936
- }
1937
- printJSXAttribute(node) {
1938
- this.out += jsxAttributeNameText(node.name);
1939
- this.out += this.jsxAttributeValueClauseText(node.value);
1940
- }
1941
- jsxAttributeValueClauseText(value) {
1942
- switch (nodeKind(value)) {
1943
- case ABSENT_NODE_KIND: return "";
1944
- default: return `=${this.jsxAttributeValueText(value)}`;
1945
- }
1946
- }
1947
- jsxAttributeValueText(value) {
1948
- switch (value.type) {
1949
- case "Literal": return this.capture(() => this.printLiteral(value));
1950
- case "JSXExpressionContainer": {
1951
- const container = value;
1952
- return `{${this.sequenceNodeText(container.expression)}}`;
1953
- }
1954
- default: return this.sequenceNodeText(value);
1955
- }
1956
- }
1957
- printJSXChild(child) {
1958
- switch (child.type) {
1959
- case "JSXText":
1960
- this.out += child.value;
1961
- break;
1962
- case "JSXElement":
1963
- this.printJSXElement(child);
1964
- break;
1965
- case "JSXFragment":
1966
- this.printJSXFragment(child);
1967
- break;
1968
- case "JSXExpressionContainer":
1969
- this.out += "{";
1970
- this.printNode(child.expression, PREC.Sequence);
1971
- this.out += "}";
1972
- break;
1973
- case "JSXSpreadChild":
1974
- this.out += "{...";
1975
- this.printNode(child.expression, PREC.Assignment);
1976
- this.out += "}";
1977
- break;
1978
- default: this.printNode(child, PREC.Sequence);
1979
- }
1980
- }
1981
- printTSAsExpression(node, prec) {
1982
- const myPrec = PREC.Relational;
1983
- const whole = `${this.printExpressionToString(node.expression, myPrec)} as ${this.printTSTypeToString(node.typeAnnotation)}`;
1984
- if (myPrec < prec) this.out += `(${whole})`;
1985
- else this.out += whole;
1986
- }
1987
- printTSSatisfiesExpression(node, prec) {
1988
- const myPrec = PREC.Relational;
1989
- const whole = `${this.printExpressionToString(node.expression, myPrec)} satisfies ${this.printTSTypeToString(node.typeAnnotation)}`;
1990
- if (myPrec < prec) this.out += `(${whole})`;
1991
- else this.out += whole;
1992
- }
1993
- printTSTypeAssertion(node, _prec) {
1994
- this.out += `<${this.printTSTypeToString(node.typeAnnotation)}>`;
1995
- this.printNode(node.expression, PREC.Unary);
1996
- }
1997
- printTSInstantiationExpression(node, _prec) {
1998
- this.printNode(node.expression, PREC.Member);
1999
- this.printTSTypeParameterInstantiation(node.typeArguments);
2000
- }
2001
- printStatement(node) {
2002
- const n = node;
2003
- this.printAttachedComments(n, "leadingComments");
2004
- switch (n.type) {
2005
- case "BlockStatement":
2006
- this.printBlockStatement(n);
2007
- break;
2008
- case "VariableDeclaration":
2009
- this.printVariableDeclaration(n);
2010
- this.out += ";";
2011
- break;
2012
- case "FunctionDeclaration":
2013
- case "TSDeclareFunction":
2014
- this.printFunction(n, PREC.Sequence);
2015
- break;
2016
- case "ClassDeclaration":
2017
- this.printClass(n, PREC.Sequence);
2018
- break;
2019
- case "ExpressionStatement":
2020
- this.printExpressionStatement(n);
2021
- break;
2022
- case "IfStatement":
2023
- this.printIfStatement(n);
2024
- break;
2025
- case "ForStatement":
2026
- this.printForStatement(n);
2027
- break;
2028
- case "ForInStatement":
2029
- this.printForInStatement(n);
2030
- break;
2031
- case "ForOfStatement":
2032
- this.printForOfStatement(n);
2033
- break;
2034
- case "WhileStatement":
2035
- this.printWhileStatement(n);
2036
- break;
2037
- case "DoWhileStatement":
2038
- this.printDoWhileStatement(n);
2039
- break;
2040
- case "ReturnStatement":
2041
- this.printReturnStatement(n);
2042
- break;
2043
- case "ThrowStatement":
2044
- this.out += "throw ";
2045
- this.printNode(n.argument, PREC.Sequence);
2046
- this.out += ";";
2047
- break;
2048
- case "TryStatement":
2049
- this.printTryStatement(n);
2050
- break;
2051
- case "SwitchStatement":
2052
- this.printSwitchStatement(n);
2053
- break;
2054
- case "LabeledStatement":
2055
- this.printLabeledStatement(n);
2056
- break;
2057
- case "BreakStatement":
2058
- case "ContinueStatement":
2059
- case "DebuggerStatement":
2060
- case "EmptyStatement":
2061
- this.printNode(n, PREC.Sequence);
2062
- break;
2063
- case "WithStatement":
2064
- this.printWithStatement(n);
2065
- break;
2066
- case "ImportDeclaration":
2067
- this.printImportDeclaration(n);
2068
- break;
2069
- case "ExportNamedDeclaration":
2070
- this.printExportNamedDeclaration(n);
2071
- break;
2072
- case "ExportDefaultDeclaration":
2073
- this.printExportDefaultDeclaration(n);
2074
- break;
2075
- case "ExportAllDeclaration":
2076
- this.printExportAllDeclaration(n);
2077
- break;
2078
- case "TSTypeAliasDeclaration":
2079
- this.printTSTypeAliasDeclaration(n);
2080
- break;
2081
- case "TSInterfaceDeclaration":
2082
- this.printTSInterfaceDeclaration(n);
2083
- break;
2084
- case "TSEnumDeclaration":
2085
- this.printTSEnumDeclaration(n);
2086
- break;
2087
- case "TSModuleDeclaration":
2088
- this.printTSModuleDeclaration(n);
2089
- break;
2090
- case "TSImportEqualsDeclaration":
2091
- this.printTSImportEqualsDeclaration(n);
2092
- break;
2093
- case "TSExportAssignment":
2094
- case "TSNamespaceExportDeclaration":
2095
- this.printNode(n, PREC.Sequence);
2096
- break;
2097
- default: this.printUnhandledStatement(n);
2098
- }
2099
- this.printAttachedComments(n, "trailingComments");
2100
- }
2101
- printUnhandledStatement(node) {
2102
- if (!isTSTypeNode(node.type)) throw new Error(`Printer: unhandled statement kind ${node.type}`);
2103
- this.printTSType(node);
2104
- this.out += ";";
2105
- }
2106
- /**
2107
- * Emits the comments `attachComments` folded into the tree
2108
- * (`leadingComments` before the statement, `trailingComments` on the
2109
- * statement's last line). The flat `opts.comments` path only serves direct
2110
- * `printProgram` calls on freshly parsed trees; instrumented trees carry
2111
- * their comments attached to nodes.
2112
- */
2113
- printAttachedComments(node, field) {
2114
- const comments = node[field];
2115
- if (!Array.isArray(comments)) return;
2116
- comments.forEach((comment) => this.printAttachedComment(comment, field));
2117
- }
2118
- printAttachedComment(comment, field) {
2119
- switch (field) {
2120
- case "leadingComments":
2121
- this.out += `${this.indent()}${commentText(comment)}\n`;
2122
- break;
2123
- default: this.out += `${commentText(comment)} `;
2124
- }
2125
- }
2126
- printBlockStatement(node) {
2127
- switch (node.body.length) {
2128
- case 0:
2129
- this.out += "{}";
2130
- break;
2131
- default:
2132
- this.out += "{\n";
2133
- this.out += this.indentedBodyText(node.body, (statement) => this.printStatement(statement));
2134
- this.out += `${this.indent()}}`;
2135
- }
2136
- }
2137
- printExpressionStatement(node) {
2138
- if (this.isDirective(node.directive)) {
2139
- this.out += JSON.stringify(node.directive) + ";";
2076
+ case "JSXElement":
2077
+ printJSXElement(state, child);
2140
2078
  return;
2141
- }
2142
- this.printNode(node.expression, PREC.Sequence);
2143
- this.out += ";";
2144
- }
2145
- isDirective(directive) {
2146
- return directive != null && directive !== "";
2147
- }
2148
- printIfStatement(node) {
2149
- this.out += "if (";
2150
- this.printNode(node.test, PREC.Sequence);
2151
- this.out += ") ";
2152
- this.printStatementOrBlock(node.consequent);
2153
- if (node.alternate) {
2154
- this.out += " else ";
2155
- this.printStatementOrBlock(node.alternate);
2156
- }
2157
- }
2158
- printStatementOrBlock(node) {
2159
- if (node.type === "BlockStatement") this.printBlockStatement(node);
2160
- else this.printStatement(node);
2161
- }
2162
- printWhileStatement(node) {
2163
- this.out += "while (";
2164
- this.printNode(node.test, PREC.Sequence);
2165
- this.out += ") ";
2166
- this.printStatementOrBlock(node.body);
2167
- }
2168
- printDoWhileStatement(node) {
2169
- this.out += "do ";
2170
- this.printStatementOrBlock(node.body);
2171
- this.out += " while (";
2172
- this.printNode(node.test, PREC.Sequence);
2173
- this.out += ");";
2174
- }
2175
- printForStatement(node) {
2176
- this.out += "for (";
2177
- this.printDeclarationOrExpression(node.init);
2178
- this.out += "; ";
2179
- this.out += this.optionalSequenceText(node.test);
2180
- this.out += "; ";
2181
- this.out += this.optionalSequenceText(node.update);
2182
- this.out += ") ";
2183
- this.printStatementOrBlock(node.body);
2184
- }
2185
- printDeclarationOrExpression(node) {
2186
- switch (nodeKind(node)) {
2187
- case "VariableDeclaration":
2188
- this.printVariableDeclaration(node);
2189
- break;
2190
- case ABSENT_NODE_KIND: break;
2191
- default: this.printNode(node, PREC.Sequence);
2192
- }
2193
- }
2194
- optionalSequenceText(node) {
2195
- switch (nodeKind(node)) {
2196
- case ABSENT_NODE_KIND: return "";
2197
- default: return this.sequenceNodeText(node);
2198
- }
2199
- }
2200
- printForInStatement(node) {
2201
- this.out += "for (";
2202
- if (node.left.type === "VariableDeclaration") this.printVariableDeclaration(node.left);
2203
- else this.printNode(node.left, PREC.Sequence);
2204
- this.out += " in ";
2205
- this.printNode(node.right, PREC.Sequence);
2206
- this.out += ") ";
2207
- this.printStatementOrBlock(node.body);
2208
- }
2209
- printForOfStatement(node) {
2210
- switch (node.await) {
2211
- case true:
2212
- this.out += "for await (";
2213
- break;
2214
- default: this.out += "for (";
2215
- }
2216
- this.printDeclarationOrExpression(node.left);
2217
- this.out += " of ";
2218
- this.out += this.sequenceNodeText(node.right);
2219
- this.out += ") ";
2220
- this.printStatementOrBlock(node.body);
2221
- }
2222
- printReturnStatement(node) {
2223
- if (node.argument) {
2224
- this.out += "return ";
2225
- this.printNode(node.argument, PREC.Sequence);
2226
- this.out += ";";
2227
- } else this.out += "return;";
2228
- }
2229
- printWithStatement(node) {
2230
- this.out += "with (";
2231
- this.printNode(node.object, PREC.Sequence);
2232
- this.out += ") ";
2233
- this.printStatementOrBlock(node.body);
2234
- }
2235
- printSwitchStatement(node) {
2236
- this.out += `switch (${this.sequenceNodeText(node.discriminant)}) {\n`;
2237
- this.indentLevel++;
2238
- this.out += node.cases.map((switchCase) => `${this.indent()}${this.capture(() => this.printSwitchCase(switchCase))}`).join("");
2239
- this.indentLevel--;
2240
- this.out += `${this.indent()}}`;
2241
- }
2242
- printSwitchCase(node) {
2243
- this.out += this.switchCaseHeaderText(node);
2244
- this.out += this.indentedBodyText(node.consequent, (statement) => this.printStatement(statement));
2245
- }
2246
- switchCaseHeaderText(node) {
2247
- switch (Boolean(node.test)) {
2248
- case true: return `case ${this.sequenceNodeText(node.test)}:\n`;
2249
- default: return "default:\n";
2250
- }
2251
- }
2252
- printLabeledStatement(node) {
2253
- this.out += `${node.label.name}: `;
2254
- this.printStatement(node.body);
2255
- }
2256
- printTryStatement(node) {
2257
- this.out += "try ";
2258
- this.printBlockStatement(node.block);
2259
- this.printCatchClause(node.handler);
2260
- this.printFinallyClause(node.finalizer);
2261
- }
2262
- printCatchClause(handler) {
2263
- if (!handler) return;
2264
- this.out += ` catch${this.catchParamText(handler.param)} `;
2265
- this.printBlockStatement(handler.body);
2266
- }
2267
- catchParamText(param) {
2268
- switch (nodeKind(param)) {
2269
- case ABSENT_NODE_KIND: return "";
2270
- default: return ` (${this.catchParamBodyText(param)})`;
2271
- }
2272
- }
2273
- catchParamBodyText(param) {
2274
- switch (param.type) {
2275
- case "Identifier": return this.identifierWithOptionalText(param);
2276
- default: return this.sequenceNodeText(param);
2277
- }
2278
- }
2279
- printFinallyClause(finalizer) {
2280
- if (!finalizer) return;
2281
- this.out += " finally ";
2282
- this.printBlockStatement(finalizer);
2283
- }
2284
- printVariableDeclaration(node) {
2285
- this.out += `${flagText(node.declare, "declare ")}${node.kind} `;
2286
- this.out += node.declarations.map((declaration) => this.variableDeclaratorText(declaration)).join(", ");
2287
- }
2288
- variableDeclaratorText(node) {
2289
- return this.capture(() => this.printVariableDeclarator(node));
2290
- }
2291
- printVariableDeclarator(node) {
2292
- const id = node.id;
2293
- const declarator = node;
2294
- this.out += this.bindingTargetText(id);
2295
- this.out += flagText(declarator.definite, "!");
2296
- this.out += this.typeAnnotationText(id.typeAnnotation);
2297
- this.out += this.initializerText(node.init);
2298
- }
2299
- bindingTargetText(id) {
2300
- switch (id.type) {
2301
- case "Identifier": return `${bindingNameText(id)}${flagText(id.optional, "?")}`;
2302
- default: return this.sequenceNodeText(id);
2303
- }
2304
- }
2305
- identifierWithOptionalText(node) {
2306
- return `${bindingNameText(node)}${flagText(node.optional, "?")}${this.typeAnnotationText(node.typeAnnotation)}`;
2307
- }
2308
- printParams(params) {
2309
- this.out += params.map((param) => this.paramText(param)).join(", ");
2310
- }
2311
- paramText(param) {
2312
- switch (parameterForm(param)) {
2313
- case "rest": return this.restParamText(param);
2314
- case "property": return this.parameterPropertyText(param);
2315
- default: return this.formalParameterText(param);
2316
- }
2317
- }
2318
- restParamText(param) {
2319
- return `...${this.assignmentNodeText(param["argument"])}${this.typeAnnotationText(param["typeAnnotation"])}`;
2320
- }
2321
- parameterPropertyText(param) {
2322
- return `${this.capture(() => this.printDecorators(param["decorators"]))}${parameterPropertyModifiers(param)}${this.parameterPropertyTargetText(param["parameter"])}`;
2323
- }
2324
- parameterPropertyTargetText(parameter) {
2325
- switch (nodeKind(parameter)) {
2326
- case "Identifier": return this.identifierWithOptionalText(parameter);
2327
- default: return this.sequenceNodeText(parameter);
2328
- }
2329
- }
2330
- formalParameterText(param) {
2331
- return `${this.capture(() => this.printDecorators(param["decorators"]))}${this.formalParameterBodyText(param)}`;
2332
- }
2333
- formalParameterBodyText(param) {
2334
- switch (param["type"] === "Identifier") {
2335
- case true: return this.identifierWithOptionalText(param);
2336
- default: return `${this.assignmentNodeText(param)}${this.typeAnnotationText(param["typeAnnotation"])}`;
2337
- }
2338
- }
2339
- printClassBody(node) {
2340
- switch (node.body.length) {
2341
- case 0:
2342
- this.out += "{}";
2343
- break;
2344
- default:
2345
- this.out += "{\n";
2346
- this.out += this.indentedBodyText(node.body, (element) => this.printNode(element, PREC.Sequence));
2347
- this.out += `${this.indent()}}`;
2348
- }
2349
- }
2350
- indentedBodyText(items, print) {
2351
- this.indentLevel++;
2352
- const body = items.map((item) => `${this.indent()}${this.capture(() => print(item))}\n`).join("");
2353
- this.indentLevel--;
2354
- return body;
2355
- }
2356
- printMethodDefinition(node) {
2357
- const fn = node.value;
2358
- this.out += this.capture(() => this.printDecorators(node.decorators));
2359
- this.out += methodDefinitionPrefix(node, fn);
2360
- this.out += this.propertyKeyText(node.key, node.computed === true, PREC.Sequence);
2361
- this.out += flagText(node.optional, "?");
2362
- this.printFunctionTail(fn);
2363
- }
2364
- printPropertyDefinition(node) {
2365
- this.out += this.capture(() => this.printDecorators(node.decorators));
2366
- this.out += propertyDefinitionModifiers(node);
2367
- this.out += this.propertyKeyText(node.key, node.computed === true, PREC.Sequence);
2368
- this.out += flagText(node.optional, "?");
2369
- this.out += flagText(node.definite, "!");
2370
- this.out += this.typeAnnotationText(node.typeAnnotation);
2371
- this.out += this.initializerText(node.value);
2372
- this.out += ";";
2373
- }
2374
- printAccessorProperty(node) {
2375
- this.out += this.capture(() => this.printDecorators(node.decorators));
2376
- this.out += flagText(node.accessibility, `${node.accessibility} `);
2377
- this.out += flagText(node.static, "static ");
2378
- this.out += flagText(node.override, "override ");
2379
- this.out += "accessor ";
2380
- this.out += this.propertyKeyText(node.key, node.computed === true, PREC.Sequence);
2381
- this.out += flagText(node.definite, "!");
2382
- this.out += this.typeAnnotationText(node.typeAnnotation);
2383
- this.out += this.initializerText(node.value);
2384
- this.out += ";";
2385
- }
2386
- initializerText(value) {
2387
- return flagText(value, ` = ${this.assignmentNodeText(value)}`);
2388
- }
2389
- printStaticBlock(node) {
2390
- this.out += "static {\n";
2391
- this.indentLevel++;
2392
- for (const stmt of node.body) {
2393
- this.out += this.indent();
2394
- this.printStatement(stmt);
2395
- this.out += "\n";
2396
- }
2397
- this.indentLevel--;
2398
- this.out += `${this.indent()}}`;
2399
- }
2400
- printImportDeclaration(node) {
2401
- const source = this.printImportSource(node.source, node.attributes);
2402
- this.out += `import ${importKindText(node)}${this.importClauseText(node, source)};`;
2403
- }
2404
- importClauseText(node, source) {
2405
- switch (node.specifiers.length === 0) {
2406
- case true: return source;
2407
- default: return `${importBindingsText(node.specifiers)} from ${source}`;
2408
- }
2409
- }
2410
- printImportSource(source, attrs) {
2411
- return `${source.raw ?? JSON.stringify(source.value)}${importAttributesText(attrs)}`;
2412
- }
2413
- printExportNamedDeclaration(node) {
2414
- switch (node.declaration === null) {
2415
- case false:
2416
- this.out += `export ${this.capture(() => this.printStatement(node.declaration))}`;
2417
- break;
2418
- default: this.out += `export ${flagText(node.exportKind === "type", "type ")}{ ${node.specifiers.map((specifier) => exportSpecifierText(specifier)).join(", ")} }${this.exportSourceClauseText(node)};`;
2419
- }
2420
- }
2421
- exportSourceClauseText(node) {
2422
- if (!node.source) return "";
2423
- return ` from ${JSON.stringify(node.source.value)}${importAttributesText(node.attributes)}`;
2424
- }
2425
- printExportDefaultDeclaration(node) {
2426
- const declaration = node.declaration;
2427
- this.out += "export default ";
2428
- switch (BARE_DEFAULT_EXPORT_KINDS[declaration.type] === true) {
2429
- case true:
2430
- this.printStatement(declaration);
2431
- break;
2432
- default:
2433
- this.printNode(declaration, PREC.Assignment);
2434
- this.out += ";";
2435
- }
2436
- }
2437
- printExportAllDeclaration(node) {
2438
- this.out += `export ${flagText(node.exportKind === "type", "type ")}*${exportedNameClauseText(node.exported)}`;
2439
- this.out += ` from ${JSON.stringify(node.source.value)}${importAttributesText(node.attributes)};`;
2440
- }
2441
- printTSTypeAliasDeclaration(node) {
2442
- this.out += `${flagText(node.declare, "declare ")}type ${node.id.name}${this.typeParametersText(node.typeParameters)} = ${this.printTSTypeToString(node.typeAnnotation)};`;
2443
- }
2444
- printTSInterfaceDeclaration(node) {
2445
- this.out += `${flagText(node.declare, "declare ")}interface ${node.id.name}${this.typeParametersText(node.typeParameters)}`;
2446
- this.out += this.interfaceExtendsText(node.extends);
2447
- this.out += " ";
2448
- this.printTSInterfaceBody(node.body);
2449
- }
2450
- interfaceExtendsText(extensions) {
2451
- const rendered = extensions.map((heritage) => this.heritageText(heritage)).join(", ");
2452
- return flagText(rendered, ` extends ${rendered}`);
2453
- }
2454
- printTSInterfaceBody(node) {
2455
- switch (node.body.length) {
2456
- case 0:
2457
- this.out += "{}";
2458
- break;
2459
- default:
2460
- this.out += "{\n";
2461
- this.out += this.indentedBodyText(node.body, (member) => this.printTSSignature(member));
2462
- this.out += `${this.indent()}}`;
2463
- }
2464
- }
2465
- printTSSignature(sig) {
2466
- switch (sig.type) {
2467
- case "TSPropertySignature":
2468
- this.printTSPropertySignature(sig);
2469
- break;
2470
- case "TSIndexSignature":
2471
- this.printTSIndexSignature(sig);
2472
- break;
2473
- case "TSCallSignatureDeclaration":
2474
- this.printTSCallSignature(sig);
2475
- break;
2476
- case "TSConstructSignatureDeclaration":
2477
- this.printTSConstructSignature(sig);
2478
- break;
2479
- case "TSMethodSignature":
2480
- this.printTSMethodSignature(sig);
2481
- break;
2482
- default: this.out += `/* sig:${sig.type} */;`;
2483
- }
2484
- }
2485
- printTSPropertySignature(node) {
2486
- this.out += `${flagText(node.readonly, "readonly ")}${this.propertyKeyText(node.key, node.computed === true, PREC.Sequence)}${flagText(node.optional, "?")}${this.typeAnnotationText(node.typeAnnotation)};`;
2487
- }
2488
- printTSIndexSignature(node) {
2489
- const parameters = node.parameters.map((parameter) => this.indexParameterText(parameter)).join(", ");
2490
- this.out += `${flagText(node.readonly, "readonly ")}${flagText(node.static, "static ")}[${parameters}]${this.typeAnnotationText(node.typeAnnotation)};`;
2491
- }
2492
- indexParameterText(parameter) {
2493
- const annotation = parameter.typeAnnotation;
2494
- return `${parameter.name}: ${this.printTSTypeToString(annotation.typeAnnotation)}`;
2495
- }
2496
- printTSCallSignature(node) {
2497
- this.out += `${this.typeParametersText(node.typeParameters)}(${this.paramsText(node.params)})${this.typeAnnotationText(node.returnType)};`;
2498
- }
2499
- printTSConstructSignature(node) {
2500
- this.out += `new ${this.typeParametersText(node.typeParameters)}(${this.paramsText(node.params)})${this.typeAnnotationText(node.returnType)};`;
2501
- }
2502
- printTSMethodSignature(node) {
2503
- this.out += `${methodKindText(node.kind)}${this.propertyKeyText(node.key, node.computed === true, PREC.Sequence)}${flagText(node.optional, "?")}${this.typeParametersText(node.typeParameters)}(${this.paramsText(node.params)})${this.typeAnnotationText(node.returnType)};`;
2504
- }
2505
- printTSEnumDeclaration(node) {
2506
- this.out += `${flagText(node.declare, "declare ")}${flagText(node.const, "const ")}enum ${node.id.name} {\n`;
2507
- this.out += this.indentedBodyText(node.body.members, (member) => this.printEnumMember(member));
2508
- this.out += `${this.indent()}}`;
2509
- }
2510
- printEnumMember(member) {
2511
- this.out += `${this.identifierOrLiteralNameText(member.id)}${this.initializerText(member.initializer)},`;
2512
- }
2513
- identifierOrLiteralNameText(id) {
2514
- switch (id.type) {
2515
- case "Identifier": return id.name;
2516
- case "Literal": return this.capture(() => this.printLiteral(id));
2517
- default: return this.sequenceNodeText(id);
2518
- }
2519
- }
2520
- printTSModuleDeclaration(node) {
2521
- this.out += `${flagText(node.declare, "declare ")}${this.moduleHeaderText(node)}${this.moduleBodyText(node)}`;
2522
- }
2523
- moduleHeaderText(node) {
2524
- switch (Boolean(node.global)) {
2525
- case true: return "global ";
2526
- default: return `${node.kind} ${this.identifierOrLiteralNameText(node.id)}`;
2527
- }
2528
- }
2529
- moduleBodyText(node) {
2530
- switch (Boolean(node.body)) {
2531
- case true: return ` ${this.capture(() => this.printTSModuleBlock(node.body))}`;
2532
- default: return ";";
2533
- }
2534
- }
2535
- printTSModuleBlock(node) {
2536
- this.out += "{\n";
2537
- this.out += this.indentedBodyText(node.body, (statement) => this.printStatement(statement));
2538
- this.out += `${this.indent()}}`;
2539
- }
2540
- printTSImportEqualsDeclaration(node) {
2541
- this.out += `import ${flagText(node.importKind === "type", "type ")}${node.id.name} = ${this.moduleReferenceText(node.moduleReference)};`;
2542
- }
2543
- moduleReferenceText(reference) {
2544
- switch (reference.type) {
2545
- case "TSExternalModuleReference": return `require(${externalModuleArgumentText(reference.expression.value)})`;
2546
- default: return this.sequenceNodeText(reference);
2547
- }
2548
- }
2549
- printTSType(node) {
2550
- this.out += this.printTSTypeToString(node);
2551
- }
2552
- printTSTypeToString(node) {
2553
- const saved = this.out;
2554
- this.out = "";
2555
- this.doPrintTSType(node);
2556
- const result = this.out;
2557
- this.out = saved;
2558
- return result;
2559
- }
2560
- doPrintTSType(node) {
2561
- switch (node.type) {
2562
- case "TSAnyKeyword":
2563
- this.out += "any";
2564
- break;
2565
- case "TSStringKeyword":
2566
- this.out += "string";
2567
- break;
2568
- case "TSBooleanKeyword":
2569
- this.out += "boolean";
2570
- break;
2571
- case "TSNumberKeyword":
2572
- this.out += "number";
2573
- break;
2574
- case "TSBigIntKeyword":
2575
- this.out += "bigint";
2576
- break;
2577
- case "TSSymbolKeyword":
2578
- this.out += "symbol";
2579
- break;
2580
- case "TSVoidKeyword":
2581
- this.out += "void";
2582
- break;
2583
- case "TSUndefinedKeyword":
2584
- this.out += "undefined";
2585
- break;
2586
- case "TSNullKeyword":
2587
- this.out += "null";
2588
- break;
2589
- case "TSNeverKeyword":
2590
- this.out += "never";
2591
- break;
2592
- case "TSUnknownKeyword":
2593
- this.out += "unknown";
2594
- break;
2595
- case "TSObjectKeyword":
2596
- this.out += "object";
2597
- break;
2598
- case "TSIntrinsicKeyword":
2599
- this.out += "intrinsic";
2600
- break;
2601
- case "TSThisType":
2602
- this.out += "this";
2603
- break;
2604
- case "TSTypeReference": {
2605
- const n = node;
2606
- this.printTSTypeName(n.typeName);
2607
- this.out += this.typeArgumentsText(n.typeArguments);
2608
- break;
2609
- }
2610
- case "TSUnionType": {
2611
- const n = node;
2612
- this.out += this.tSTypeListText(n.types, " | ");
2613
- break;
2614
- }
2615
- case "TSIntersectionType": {
2616
- const n = node;
2617
- this.out += this.tSTypeListText(n.types, " & ");
2618
- break;
2619
- }
2620
- case "TSArrayType": {
2621
- const n = node;
2622
- this.out += `${this.arrayElementTypeText(n.elementType)}[]`;
2623
- break;
2624
- }
2625
- case "TSTypeLiteral": {
2626
- const n = node;
2627
- this.printTSTypeLiteral(n.members);
2628
- break;
2629
- }
2630
- case "TSTupleType": {
2631
- const n = node;
2632
- this.printTupleType(n.elementTypes);
2633
- break;
2634
- }
2635
- case "TSConditionalType": {
2636
- const n = node;
2637
- this.doPrintTSType(n.checkType);
2638
- this.out += " extends ";
2639
- this.doPrintTSType(n.extendsType);
2640
- this.out += " ? ";
2641
- this.doPrintTSType(n.trueType);
2642
- this.out += " : ";
2643
- this.doPrintTSType(n.falseType);
2644
- break;
2645
- }
2646
- case "TSInferType": {
2647
- const n = node;
2648
- this.out += `infer ${n.typeParameter.name.name}`;
2649
- this.printTypeClause(" extends ", n.typeParameter.constraint);
2650
- break;
2651
- }
2652
- case "TSTypeQuery": {
2653
- const n = node;
2654
- this.out += "typeof ";
2655
- this.printTypeQueryName(n);
2656
- this.out += this.typeArgumentsText(n.typeArguments);
2657
- break;
2658
- }
2659
- case "TSImportType":
2660
- this.printTSImportType(node);
2661
- break;
2662
- case "TSTypeOperator": {
2663
- const n = node;
2664
- this.out += `${n.operator} `;
2665
- this.doPrintTSType(n.typeAnnotation);
2666
- break;
2667
- }
2668
- case "TSMappedType":
2669
- this.printMappedType(node);
2670
- break;
2671
- case "TSTemplateLiteralType":
2672
- this.printTSTemplateLiteral(node);
2673
- break;
2674
- case "TSFunctionType":
2675
- this.printTSFunctionType(node);
2676
- break;
2677
- case "TSConstructorType":
2678
- this.printTSConstructorType(node);
2679
- break;
2680
- case "TSTypePredicate":
2681
- this.printTSTypePredicate(node);
2682
- break;
2683
- case "TSIndexedAccessType": {
2684
- const n = node;
2685
- this.doPrintTSType(n.objectType);
2686
- this.out += "[";
2687
- this.doPrintTSType(n.indexType);
2688
- this.out += "]";
2689
- break;
2690
- }
2691
- case "TSLiteralType":
2692
- this.printTSLiteralType(node.literal);
2693
- break;
2694
- case "TSParenthesizedType": {
2695
- const n = node;
2696
- this.out += "(";
2697
- this.doPrintTSType(n.typeAnnotation);
2698
- this.out += ")";
2699
- break;
2700
- }
2701
- case "TSJSDocNullableType":
2702
- this.printJSDocPostfixModifier(node, "?");
2703
- break;
2704
- case "TSJSDocNonNullableType":
2705
- this.printJSDocPostfixModifier(node, "!");
2706
- break;
2707
- case "TSJSDocUnknownType":
2708
- this.out += "?";
2709
- break;
2710
- default: this.out += `/* type:${node.type} */`;
2711
- }
2712
- }
2713
- tSTypeListText(types, separator) {
2714
- return types.map((type) => this.printTSTypeToString(type)).join(separator);
2715
- }
2716
- arrayElementTypeText(type) {
2717
- const printed = this.printTSTypeToString(type);
2718
- switch (ARRAY_ELEMENT_WRAPPED_KINDS[type.type] === true) {
2719
- case true: return `(${printed})`;
2720
- default: return printed;
2721
- }
2722
- }
2723
- printTSTypeLiteral(members) {
2724
- const rendered = members.map((member) => this.signatureText(member)).join("; ");
2725
- switch (members.length) {
2726
- case 0:
2727
- this.out += "{}";
2728
- break;
2729
- default: this.out += `{ ${rendered} }`;
2730
- }
2731
- }
2732
- signatureText(member) {
2733
- const printed = this.capture(() => this.printTSSignature(member));
2734
- switch (printed.endsWith(";")) {
2735
- case true: return printed.slice(0, -1);
2736
- default: return printed;
2737
- }
2738
- }
2739
- printTupleType(elements) {
2740
- this.out += `[${elements.map((element) => this.capture(() => this.printTupleElement(element))).join(", ")}]`;
2741
- }
2742
- printTupleElement(element) {
2743
- const tupleElement = element;
2744
- switch (tupleElement.type) {
2745
- case "TSRestType":
2746
- this.out += "...";
2747
- this.doPrintTSType(tupleElement.typeAnnotation);
2748
- break;
2749
- case "TSOptionalType":
2750
- this.doPrintTSType(tupleElement.typeAnnotation);
2751
- this.out += "?";
2752
- break;
2753
- case "TSNamedTupleMember":
2754
- this.printNamedTupleMember(tupleElement);
2755
- break;
2756
- default: this.doPrintTSType(tupleElement);
2757
- }
2758
- }
2759
- printNamedTupleMember(member) {
2760
- this.out += `${member.label.name}${flagText(member.optional, "?")}: `;
2761
- this.printTupleElement(member.elementType);
2762
- }
2763
- printTypeClause(keyword, type) {
2764
- if (!type) return;
2765
- this.out += keyword;
2766
- this.doPrintTSType(type);
2767
- }
2768
- printTypeQueryName(node) {
2769
- switch (node.exprName.type) {
2770
- case "TSImportType":
2771
- this.doPrintTSType(node.exprName);
2772
- break;
2773
- default: this.printTSTypeName(node.exprName);
2774
- }
2775
- }
2776
- printTSImportType(node) {
2777
- this.printTSImportTypeSource(node);
2778
- if (node.qualifier) {
2779
- this.out += ".";
2780
- this.printTSImportTypeQualifier(node.qualifier);
2781
- }
2782
- this.out += this.typeArgumentsText(node.typeArguments);
2783
- }
2784
- printTSImportTypeSource(node) {
2785
- this.out += `import(${JSON.stringify(node.source.value)}`;
2786
- this.out += flagText(node.options, `, ${this.assignmentNodeText(node.options)}`);
2787
- this.out += ")";
2788
- }
2789
- printMappedType(node) {
2790
- this.out += "{ ";
2791
- this.printMappedTypeModifier(node.readonly, "readonly ");
2792
- this.out += `[${node.key.name} in `;
2793
- this.doPrintTSType(node.constraint);
2794
- this.printTypeClause(" as ", node.nameType);
2795
- this.out += "]";
2796
- this.printMappedTypeModifier(node.optional, "?");
2797
- this.printTypeClause(": ", node.typeAnnotation);
2798
- this.out += " }";
2799
- }
2800
- printMappedTypeModifier(modifier, rendered) {
2801
- switch (modifier) {
2802
- case true:
2803
- this.out += rendered;
2804
- break;
2805
- case "+":
2806
- this.out += `+${rendered}`;
2807
- break;
2808
- case "-": this.out += `-${rendered}`;
2809
- }
2810
- }
2811
- printTSTemplateLiteral(node) {
2812
- this.out += `\`${node.quasis.map((quasi, index) => this.templateTypeQuasiText(quasi, node.types[index])).join("")}\``;
2813
- }
2814
- templateTypeQuasiText(quasi, type) {
2815
- switch (quasi.tail) {
2816
- case true: return quasi.value.raw;
2817
- default: return `${quasi.value.raw}\${${this.printTSTypeToString(type)}}`;
2818
- }
2819
- }
2820
- printTSFunctionType(node) {
2821
- this.out += `${this.typeParametersText(node.typeParameters)}(${this.paramsText(node.params)}) => ${this.printTSTypeToString(node.returnType.typeAnnotation)}`;
2822
- }
2823
- printTSConstructorType(node) {
2824
- this.out += `${flagText(node.abstract, "abstract ")}new ${this.typeParametersText(node.typeParameters)}(${this.paramsText(node.params)}) => ${this.printTSTypeToString(node.returnType.typeAnnotation)}`;
2825
- }
2826
- printTSTypePredicate(node) {
2827
- this.out += flagText(node.asserts, "asserts ");
2828
- this.out += typePredicateParameterText(node.parameterName);
2829
- this.printPredicateAnnotation(node);
2830
- }
2831
- printPredicateAnnotation(node) {
2832
- if (!node.typeAnnotation) return;
2833
- this.printTypeClause(" is ", node.typeAnnotation.typeAnnotation);
2834
- }
2835
- printTSLiteralType(literal) {
2836
- switch (nodeKind(literal)) {
2837
- case "Literal":
2838
- this.printLiteral(literal);
2839
- break;
2840
- case "TemplateLiteral":
2841
- this.printTemplateLiteral(literal);
2842
- break;
2843
- case "UnaryExpression":
2844
- this.printTSLiteralUnary(literal);
2845
- break;
2846
- default: this.printNode(literal, PREC.Sequence);
2847
- }
2848
- }
2849
- printTSLiteralUnary(unary) {
2850
- this.out += unary.operator;
2851
- this.printLiteral(unary.argument);
2852
- }
2853
- printJSDocPostfixModifier(node, marker) {
2854
- switch (Boolean(node.postfix)) {
2855
- case true:
2856
- this.doPrintTSType(node.typeAnnotation);
2857
- this.out += marker;
2858
- break;
2859
- default:
2860
- this.out += marker;
2861
- this.doPrintTSType(node.typeAnnotation);
2862
- }
2863
- }
2864
- printTSTypeName(name) {
2865
- switch (nodeKind(name)) {
2866
- case "TSQualifiedName": {
2867
- const qualified = name;
2868
- this.printTSTypeName(qualified.left);
2869
- this.out += `.${qualified.right.name}`;
2870
- break;
2871
- }
2872
- default: this.out += this.tSTypeNameLeafText(name);
2873
- }
2874
- }
2875
- tSTypeNameLeafText(name) {
2876
- switch (nodeKind(name)) {
2877
- case "Identifier": return name.name;
2878
- case "ThisExpression": return "this";
2879
- default: return this.sequenceNodeText(name);
2880
- }
2079
+ case "JSXFragment":
2080
+ printJSXFragment(state, child);
2081
+ return;
2082
+ case "JSXExpressionContainer":
2083
+ state.out += "{";
2084
+ printNodePrec(state, child.expression, PREC.Sequence);
2085
+ state.out += "}";
2086
+ return;
2087
+ case "JSXSpreadChild":
2088
+ state.out += "{...";
2089
+ printNodePrec(state, child.expression, PREC.Assignment);
2090
+ state.out += "}";
2091
+ }
2092
+ }
2093
+ function printTSAsExpression(state, node, prec) {
2094
+ const myPrec = PREC.Relational;
2095
+ const whole = `${printExpressionToString(state, node.expression, myPrec)} as ${printTSTypeToString(state, node.typeAnnotation)}`;
2096
+ if (myPrec < prec) state.out += `(${whole})`;
2097
+ else state.out += whole;
2098
+ }
2099
+ function printTSSatisfiesExpression(state, node, prec) {
2100
+ const myPrec = PREC.Relational;
2101
+ const whole = `${printExpressionToString(state, node.expression, myPrec)} satisfies ${printTSTypeToString(state, node.typeAnnotation)}`;
2102
+ if (myPrec < prec) state.out += `(${whole})`;
2103
+ else state.out += whole;
2104
+ }
2105
+ function printTSTypeAssertion(state, node, _prec) {
2106
+ state.out += `<${printTSTypeToString(state, node.typeAnnotation)}>`;
2107
+ printNodePrec(state, node.expression, PREC.Unary);
2108
+ }
2109
+ function printTSInstantiationExpression(state, node, _prec) {
2110
+ printNodePrec(state, node.expression, PREC.Member);
2111
+ printTSTypeParameterInstantiation(state, node.typeArguments);
2112
+ }
2113
+ function printStatement(state, node) {
2114
+ printAttachedComments(state, node, "leadingComments");
2115
+ printStatementKind(state, node);
2116
+ printAttachedComments(state, node, "trailingComments");
2117
+ }
2118
+ function printStatementKind(state, node) {
2119
+ switch (node.type) {
2120
+ case "BlockStatement":
2121
+ printBlockStatement(state, node);
2122
+ break;
2123
+ case "VariableDeclaration":
2124
+ printVariableDeclaration(state, node);
2125
+ state.out += ";";
2126
+ break;
2127
+ case "FunctionDeclaration":
2128
+ case "FunctionExpression":
2129
+ case "TSDeclareFunction":
2130
+ case "TSEmptyBodyFunctionExpression":
2131
+ printFunction(state, node, PREC.Sequence);
2132
+ break;
2133
+ case "ClassDeclaration":
2134
+ case "ClassExpression":
2135
+ printClass(state, node, PREC.Sequence);
2136
+ break;
2137
+ case "ExpressionStatement":
2138
+ printExpressionStatement(state, node);
2139
+ break;
2140
+ case "IfStatement":
2141
+ printIfStatement(state, node);
2142
+ break;
2143
+ case "ForStatement":
2144
+ printForStatement(state, node);
2145
+ break;
2146
+ case "ForInStatement":
2147
+ printForInStatement(state, node);
2148
+ break;
2149
+ case "ForOfStatement":
2150
+ printForOfStatement(state, node);
2151
+ break;
2152
+ case "WhileStatement":
2153
+ printWhileStatement(state, node);
2154
+ break;
2155
+ case "DoWhileStatement":
2156
+ printDoWhileStatement(state, node);
2157
+ break;
2158
+ case "ReturnStatement":
2159
+ printReturnStatement(state, node);
2160
+ break;
2161
+ case "ThrowStatement":
2162
+ state.out += "throw ";
2163
+ printNodePrec(state, node.argument, PREC.Sequence);
2164
+ state.out += ";";
2165
+ break;
2166
+ case "TryStatement":
2167
+ printTryStatement(state, node);
2168
+ break;
2169
+ case "SwitchStatement":
2170
+ printSwitchStatement(state, node);
2171
+ break;
2172
+ case "LabeledStatement":
2173
+ printLabeledStatement(state, node);
2174
+ break;
2175
+ case "BreakStatement":
2176
+ case "ContinueStatement":
2177
+ case "DebuggerStatement":
2178
+ case "EmptyStatement":
2179
+ printNodePrec(state, node, PREC.Sequence);
2180
+ break;
2181
+ case "WithStatement":
2182
+ printWithStatement(state, node);
2183
+ break;
2184
+ case "ImportDeclaration":
2185
+ printImportDeclaration(state, node);
2186
+ break;
2187
+ case "ExportNamedDeclaration":
2188
+ printExportNamedDeclaration(state, node);
2189
+ break;
2190
+ case "ExportDefaultDeclaration":
2191
+ printExportDefaultDeclaration(state, node);
2192
+ break;
2193
+ case "ExportAllDeclaration":
2194
+ printExportAllDeclaration(state, node);
2195
+ break;
2196
+ case "TSTypeAliasDeclaration":
2197
+ printTSTypeAliasDeclaration(state, node);
2198
+ break;
2199
+ case "TSInterfaceDeclaration":
2200
+ printTSInterfaceDeclaration(state, node);
2201
+ break;
2202
+ case "TSEnumDeclaration":
2203
+ printTSEnumDeclaration(state, node);
2204
+ break;
2205
+ case "TSModuleDeclaration":
2206
+ printTSModuleDeclaration(state, node);
2207
+ break;
2208
+ case "TSImportEqualsDeclaration":
2209
+ printTSImportEqualsDeclaration(state, node);
2210
+ break;
2211
+ case "TSExportAssignment":
2212
+ case "TSNamespaceExportDeclaration": printNodePrec(state, node, PREC.Sequence);
2213
+ }
2214
+ }
2215
+ function printAttachedComments(state, node, field) {
2216
+ const comments = node[field];
2217
+ if (comments === void 0) return;
2218
+ comments.forEach((comment) => printAttachedComment(state, comment, field));
2219
+ }
2220
+ function printAttachedComment(state, comment, field) {
2221
+ if (field === "leadingComments") {
2222
+ state.out += `${indent(state)}${commentText(comment)}\n`;
2223
+ return;
2224
+ }
2225
+ state.out += `${commentText(comment)} `;
2226
+ }
2227
+ function printBlockStatement(state, node) {
2228
+ switch (node.body.length) {
2229
+ case 0:
2230
+ state.out += "{}";
2231
+ break;
2232
+ default:
2233
+ state.out += "{\n";
2234
+ state.out += indentedBodyText(state, node.body, (statement) => printStatement(state, statement));
2235
+ state.out += `${indent(state)}}`;
2236
+ }
2237
+ }
2238
+ function printExpressionStatement(state, node) {
2239
+ if (isDirective(node.directive)) {
2240
+ state.out += JSON.stringify(node.directive) + ";";
2241
+ return;
2242
+ }
2243
+ printNodePrec(state, node.expression, PREC.Sequence);
2244
+ state.out += ";";
2245
+ }
2246
+ function isDirective(directive) {
2247
+ return directive != null && directive !== "";
2248
+ }
2249
+ function printIfStatement(state, node) {
2250
+ state.out += "if (";
2251
+ printNodePrec(state, node.test, PREC.Sequence);
2252
+ state.out += ") ";
2253
+ printStatementOrBlock(state, node.consequent);
2254
+ if (node.alternate !== null) {
2255
+ state.out += " else ";
2256
+ printStatementOrBlock(state, node.alternate);
2257
+ }
2258
+ }
2259
+ function printStatementOrBlock(state, node) {
2260
+ if (node.type === "BlockStatement") {
2261
+ printBlockStatement(state, node);
2262
+ return;
2263
+ }
2264
+ printStatement(state, node);
2265
+ }
2266
+ function printWhileStatement(state, node) {
2267
+ state.out += "while (";
2268
+ printNodePrec(state, node.test, PREC.Sequence);
2269
+ state.out += ") ";
2270
+ printStatementOrBlock(state, node.body);
2271
+ }
2272
+ function printDoWhileStatement(state, node) {
2273
+ state.out += "do ";
2274
+ printStatementOrBlock(state, node.body);
2275
+ state.out += " while (";
2276
+ printNodePrec(state, node.test, PREC.Sequence);
2277
+ state.out += ");";
2278
+ }
2279
+ function printForStatement(state, node) {
2280
+ state.out += "for (";
2281
+ printDeclarationOrExpression(state, node.init);
2282
+ state.out += "; ";
2283
+ state.out += optionalSequenceText(state, node.test);
2284
+ state.out += "; ";
2285
+ state.out += optionalSequenceText(state, node.update);
2286
+ state.out += ") ";
2287
+ printStatementOrBlock(state, node.body);
2288
+ }
2289
+ function printDeclarationOrExpression(state, node) {
2290
+ if (node == null) return;
2291
+ printDeclarationOrExpressionNode(state, node);
2292
+ }
2293
+ function printDeclarationOrExpressionNode(state, node) {
2294
+ if (node.type === "VariableDeclaration") {
2295
+ printVariableDeclaration(state, node);
2296
+ return;
2297
+ }
2298
+ printNodePrec(state, node, PREC.Sequence);
2299
+ }
2300
+ function optionalSequenceText(state, node) {
2301
+ if (node == null) return "";
2302
+ return sequenceNodeText(state, node);
2303
+ }
2304
+ function printForInStatement(state, node) {
2305
+ state.out += "for (";
2306
+ if (node.left.type === "VariableDeclaration") printVariableDeclaration(state, node.left);
2307
+ else printNodePrec(state, node.left, PREC.Sequence);
2308
+ state.out += " in ";
2309
+ printNodePrec(state, node.right, PREC.Sequence);
2310
+ state.out += ") ";
2311
+ printStatementOrBlock(state, node.body);
2312
+ }
2313
+ function printForOfStatement(state, node) {
2314
+ if (node.await) state.out += "for await (";
2315
+ else state.out += "for (";
2316
+ printDeclarationOrExpression(state, node.left);
2317
+ state.out += " of ";
2318
+ state.out += sequenceNodeText(state, node.right);
2319
+ state.out += ") ";
2320
+ printStatementOrBlock(state, node.body);
2321
+ }
2322
+ function printReturnStatement(state, node) {
2323
+ if (node.argument !== null) {
2324
+ state.out += "return ";
2325
+ printNodePrec(state, node.argument, PREC.Sequence);
2326
+ state.out += ";";
2327
+ return;
2328
+ }
2329
+ state.out += "return;";
2330
+ }
2331
+ function printWithStatement(state, node) {
2332
+ state.out += "with (";
2333
+ printNodePrec(state, node.object, PREC.Sequence);
2334
+ state.out += ") ";
2335
+ printStatementOrBlock(state, node.body);
2336
+ }
2337
+ function printSwitchStatement(state, node) {
2338
+ state.out += `switch (${sequenceNodeText(state, node.discriminant)}) {\n`;
2339
+ state.indentLevel++;
2340
+ state.out += node.cases.map((switchCase) => `${indent(state)}${capture(state, () => printSwitchCase(state, switchCase))}`).join("");
2341
+ state.indentLevel--;
2342
+ state.out += `${indent(state)}}`;
2343
+ }
2344
+ function printSwitchCase(state, node) {
2345
+ state.out += switchCaseHeaderText(state, node);
2346
+ state.out += indentedBodyText(state, node.consequent, (statement) => printStatement(state, statement));
2347
+ }
2348
+ function switchCaseHeaderText(state, node) {
2349
+ if (node.test !== null) return `case ${sequenceNodeText(state, node.test)}:\n`;
2350
+ return "default:\n";
2351
+ }
2352
+ function printLabeledStatement(state, node) {
2353
+ state.out += `${node.label.name}: `;
2354
+ printStatement(state, node.body);
2355
+ }
2356
+ function printTryStatement(state, node) {
2357
+ state.out += "try ";
2358
+ printBlockStatement(state, node.block);
2359
+ printCatchClause(state, node.handler);
2360
+ printFinallyClause(state, node.finalizer);
2361
+ }
2362
+ function printCatchClause(state, handler) {
2363
+ if (handler == null) return;
2364
+ state.out += ` catch${catchParamText(state, handler.param)} `;
2365
+ printBlockStatement(state, handler.body);
2366
+ }
2367
+ function catchParamText(state, param) {
2368
+ if (param == null) return "";
2369
+ return ` (${catchParamBodyText(state, param)})`;
2370
+ }
2371
+ function catchParamBodyText(state, param) {
2372
+ if (param.type === "Identifier") return identifierWithOptionalText(state, param);
2373
+ return sequenceNodeText(state, param);
2374
+ }
2375
+ function printFinallyClause(state, finalizer) {
2376
+ if (finalizer == null) return;
2377
+ state.out += " finally ";
2378
+ printBlockStatement(state, finalizer);
2379
+ }
2380
+ function printVariableDeclaration(state, node) {
2381
+ state.out += `${flagText(node.declare, "declare ")}${node.kind} `;
2382
+ state.out += node.declarations.map((declaration) => variableDeclaratorText(state, declaration)).join(", ");
2383
+ }
2384
+ function variableDeclaratorText(state, node) {
2385
+ return capture(state, () => printVariableDeclarator(state, node));
2386
+ }
2387
+ function printVariableDeclarator(state, node) {
2388
+ state.out += bindingTargetText(state, node.id);
2389
+ state.out += flagText(node.definite, "!");
2390
+ state.out += typeAnnotationText(state, bindingTypeAnnotation(node.id));
2391
+ state.out += initializerText(state, node.init);
2392
+ }
2393
+ function bindingTargetText(state, id) {
2394
+ if (id.type === "Identifier") return `${bindingNameText(id)}${flagText(id.optional, "?")}`;
2395
+ return sequenceNodeText(state, id);
2396
+ }
2397
+ function identifierWithOptionalText(state, node) {
2398
+ return `${bindingNameText(node)}${flagText(node.optional, "?")}${typeAnnotationText(state, node.typeAnnotation)}`;
2399
+ }
2400
+ function printParams(state, params) {
2401
+ state.out += params.map((param) => paramText(state, param)).join(", ");
2402
+ }
2403
+ function paramText(state, param) {
2404
+ switch (param.type) {
2405
+ case "RestElement": return restParamText(state, param);
2406
+ case "TSParameterProperty": return parameterPropertyText(state, param);
2407
+ case "Identifier":
2408
+ case "ObjectPattern":
2409
+ case "ArrayPattern":
2410
+ case "AssignmentPattern": return formalParameterText(state, param);
2411
+ }
2412
+ }
2413
+ function restParamText(state, param) {
2414
+ return `...${assignmentNodeText(state, param.argument)}${typeAnnotationText(state, param.typeAnnotation)}`;
2415
+ }
2416
+ function parameterPropertyText(state, param) {
2417
+ return `${capture(state, () => printDecorators(state, param.decorators))}${parameterPropertyModifiers(param)}${parameterPropertyTargetText(state, param.parameter)}`;
2418
+ }
2419
+ function parameterPropertyTargetText(state, parameter) {
2420
+ if (parameter.type === "Identifier") return identifierWithOptionalText(state, parameter);
2421
+ return sequenceNodeText(state, parameter);
2422
+ }
2423
+ function formalParameterText(state, param) {
2424
+ return `${capture(state, () => printDecorators(state, param.decorators))}${formalParameterBodyText(state, param)}`;
2425
+ }
2426
+ function formalParameterBodyText(state, param) {
2427
+ if (param.type === "Identifier") return identifierWithOptionalText(state, param);
2428
+ return `${assignmentNodeText(state, param)}${typeAnnotationText(state, bindingTypeAnnotation(param))}`;
2429
+ }
2430
+ function printClassBody(state, node) {
2431
+ switch (node.body.length) {
2432
+ case 0:
2433
+ state.out += "{}";
2434
+ break;
2435
+ default:
2436
+ state.out += "{\n";
2437
+ state.out += indentedBodyText(state, node.body, (element) => printNodePrec(state, element, PREC.Sequence));
2438
+ state.out += `${indent(state)}}`;
2439
+ }
2440
+ }
2441
+ function indentedBodyText(state, items, print) {
2442
+ state.indentLevel++;
2443
+ const body = items.map((item) => `${indent(state)}${capture(state, () => print(item))}\n`).join("");
2444
+ state.indentLevel--;
2445
+ return body;
2446
+ }
2447
+ function printMethodDefinition(state, node) {
2448
+ const fn = node.value;
2449
+ state.out += capture(state, () => printDecorators(state, node.decorators));
2450
+ state.out += methodDefinitionPrefix(node, fn);
2451
+ state.out += propertyKeyText(state, node.key, node.computed === true, PREC.Sequence);
2452
+ state.out += flagText(node.optional, "?");
2453
+ printFunctionTail(state, fn);
2454
+ }
2455
+ function printPropertyDefinition(state, node) {
2456
+ state.out += capture(state, () => printDecorators(state, node.decorators));
2457
+ state.out += propertyDefinitionModifiers(node);
2458
+ state.out += propertyKeyText(state, node.key, node.computed === true, PREC.Sequence);
2459
+ state.out += flagText(node.optional, "?");
2460
+ state.out += flagText(node.definite, "!");
2461
+ state.out += typeAnnotationText(state, node.typeAnnotation);
2462
+ state.out += initializerText(state, node.value);
2463
+ state.out += ";";
2464
+ }
2465
+ function printAccessorProperty(state, node) {
2466
+ state.out += capture(state, () => printDecorators(state, node.decorators));
2467
+ state.out += flagText(node.accessibility, `${node.accessibility} `);
2468
+ state.out += flagText(node.static, "static ");
2469
+ state.out += flagText(node.override, "override ");
2470
+ state.out += "accessor ";
2471
+ state.out += propertyKeyText(state, node.key, node.computed === true, PREC.Sequence);
2472
+ state.out += flagText(node.definite, "!");
2473
+ state.out += typeAnnotationText(state, node.typeAnnotation);
2474
+ state.out += initializerText(state, node.value);
2475
+ state.out += ";";
2476
+ }
2477
+ function initializerText(state, value) {
2478
+ return flagText(value, ` = ${assignmentNodeText(state, value)}`);
2479
+ }
2480
+ function printStaticBlock(state, node) {
2481
+ state.out += "static {\n";
2482
+ state.indentLevel++;
2483
+ for (const stmt of node.body) {
2484
+ state.out += indent(state);
2485
+ printStatement(state, stmt);
2486
+ state.out += "\n";
2487
+ }
2488
+ state.indentLevel--;
2489
+ state.out += `${indent(state)}}`;
2490
+ }
2491
+ function printImportDeclaration(state, node) {
2492
+ const source = printImportSource(node.source, node.attributes);
2493
+ state.out += `import ${importKindText(node)}${importClauseText(node, source)};`;
2494
+ }
2495
+ function importClauseText(node, source) {
2496
+ if (node.specifiers.length === 0) return source;
2497
+ return `${importBindingsText(node.specifiers)} from ${source}`;
2498
+ }
2499
+ function printImportSource(source, attrs) {
2500
+ return `${source.raw ?? JSON.stringify(source.value)}${importAttributesText(attrs)}`;
2501
+ }
2502
+ function printExportNamedDeclaration(state, node) {
2503
+ const declaration = node.declaration;
2504
+ if (declaration !== null) {
2505
+ state.out += `export ${capture(state, () => printStatement(state, declaration))}`;
2506
+ return;
2507
+ }
2508
+ state.out += `export ${flagText(node.exportKind === "type", "type ")}{ ${node.specifiers.map((specifier) => exportSpecifierText(specifier)).join(", ")} }${exportSourceClauseText(node)};`;
2509
+ }
2510
+ function exportSourceClauseText(node) {
2511
+ if (node.source === null) return "";
2512
+ return ` from ${JSON.stringify(node.source.value)}${importAttributesText(node.attributes)}`;
2513
+ }
2514
+ function printExportDefaultDeclaration(state, node) {
2515
+ state.out += "export default ";
2516
+ printExportDefaultDeclarationBody(state, node.declaration);
2517
+ }
2518
+ function printExportDefaultDeclarationBody(state, declaration) {
2519
+ if (isBareDefaultExport(declaration)) {
2520
+ printStatement(state, declaration);
2521
+ return;
2522
+ }
2523
+ printNodePrec(state, declaration, PREC.Assignment);
2524
+ state.out += ";";
2525
+ }
2526
+ function printExportAllDeclaration(state, node) {
2527
+ state.out += `export ${flagText(node.exportKind === "type", "type ")}*${exportedNameClauseText(node.exported)}`;
2528
+ state.out += ` from ${JSON.stringify(node.source.value)}${importAttributesText(node.attributes)};`;
2529
+ }
2530
+ function printTSTypeAliasDeclaration(state, node) {
2531
+ state.out += `${flagText(node.declare, "declare ")}type ${node.id.name}${typeParametersText(state, node.typeParameters)} = ${printTSTypeToString(state, node.typeAnnotation)};`;
2532
+ }
2533
+ function printTSInterfaceDeclaration(state, node) {
2534
+ state.out += `${flagText(node.declare, "declare ")}interface ${node.id.name}${typeParametersText(state, node.typeParameters)}`;
2535
+ state.out += interfaceExtendsText(state, node.extends);
2536
+ state.out += " ";
2537
+ printTSInterfaceBody(state, node.body);
2538
+ }
2539
+ function interfaceExtendsText(state, extensions) {
2540
+ const rendered = extensions.map((heritage) => heritageText(state, heritage)).join(", ");
2541
+ return flagText(rendered, ` extends ${rendered}`);
2542
+ }
2543
+ function printTSInterfaceBody(state, node) {
2544
+ switch (node.body.length) {
2545
+ case 0:
2546
+ state.out += "{}";
2547
+ break;
2548
+ default:
2549
+ state.out += "{\n";
2550
+ state.out += indentedBodyText(state, node.body, (member) => printTSSignature(state, member));
2551
+ state.out += `${indent(state)}}`;
2552
+ }
2553
+ }
2554
+ function printTSSignature(state, sig) {
2555
+ switch (sig.type) {
2556
+ case "TSPropertySignature":
2557
+ printTSPropertySignature(state, sig);
2558
+ return;
2559
+ case "TSIndexSignature":
2560
+ printTSIndexSignature(state, sig);
2561
+ return;
2562
+ case "TSCallSignatureDeclaration":
2563
+ printTSCallSignature(state, sig);
2564
+ return;
2565
+ case "TSConstructSignatureDeclaration":
2566
+ printTSConstructSignature(state, sig);
2567
+ return;
2568
+ case "TSMethodSignature": printTSMethodSignature(state, sig);
2881
2569
  }
2882
- printTSImportTypeQualifier(qualifier) {
2883
- switch (nodeKind(qualifier)) {
2884
- case ABSENT_NODE_KIND: break;
2885
- case "Identifier":
2886
- this.out += qualifier.name;
2887
- break;
2888
- default: {
2889
- const qualified = qualifier;
2890
- this.printTSImportTypeQualifier(qualified.left);
2891
- this.out += `.${qualified.right.name}`;
2892
- }
2893
- }
2570
+ }
2571
+ function printTSPropertySignature(state, node) {
2572
+ state.out += `${flagText(node.readonly, "readonly ")}${propertyKeyText(state, node.key, node.computed === true, PREC.Sequence)}${flagText(node.optional, "?")}${typeAnnotationText(state, node.typeAnnotation)};`;
2573
+ }
2574
+ function printTSIndexSignature(state, node) {
2575
+ const parameters = node.parameters.map((parameter) => indexParameterText(state, parameter)).join(", ");
2576
+ state.out += `${flagText(node.readonly, "readonly ")}${flagText(node.static, "static ")}[${parameters}]${typeAnnotationText(state, node.typeAnnotation)};`;
2577
+ }
2578
+ function indexParameterText(state, parameter) {
2579
+ return `${parameter.name}: ${printTSTypeToString(state, parameter.typeAnnotation.typeAnnotation)}`;
2580
+ }
2581
+ function printTSCallSignature(state, node) {
2582
+ state.out += `${typeParametersText(state, node.typeParameters)}(${paramsText(state, node.params)})${typeAnnotationText(state, node.returnType)};`;
2583
+ }
2584
+ function printTSConstructSignature(state, node) {
2585
+ state.out += `new ${typeParametersText(state, node.typeParameters)}(${paramsText(state, node.params)})${typeAnnotationText(state, node.returnType)};`;
2586
+ }
2587
+ function printTSMethodSignature(state, node) {
2588
+ state.out += `${methodKindText(node.kind)}${propertyKeyText(state, node.key, node.computed === true, PREC.Sequence)}${flagText(node.optional, "?")}${typeParametersText(state, node.typeParameters)}(${paramsText(state, node.params)})${typeAnnotationText(state, node.returnType)};`;
2589
+ }
2590
+ function printTSEnumDeclaration(state, node) {
2591
+ state.out += `${flagText(node.declare, "declare ")}${flagText(node.const, "const ")}enum ${node.id.name} {\n`;
2592
+ state.out += indentedBodyText(state, node.body.members, (member) => printEnumMember(state, member));
2593
+ state.out += `${indent(state)}}`;
2594
+ }
2595
+ function printEnumMember(state, member) {
2596
+ state.out += `${identifierOrLiteralNameText(state, member.id)}${initializerText(state, member.initializer)},`;
2597
+ }
2598
+ function identifierOrLiteralNameText(state, id) {
2599
+ switch (nodeKind(id)) {
2600
+ case "Identifier": return identifierNameText(id);
2601
+ case "Literal": return literalCapture(state, id);
2602
+ default: return sequenceNodeText(state, id);
2894
2603
  }
2895
- printTSTypeAnnotation(node) {
2896
- this.out += ": ";
2897
- this.doPrintTSType(node.typeAnnotation);
2604
+ }
2605
+ function printTSModuleDeclaration(state, node) {
2606
+ state.out += `${flagText(node.declare, "declare ")}${moduleHeaderText(state, node)}${moduleBodyText(state, node)}`;
2607
+ }
2608
+ function moduleHeaderText(state, node) {
2609
+ if (node.global) return "global ";
2610
+ return `${node.kind} ${identifierOrLiteralNameText(state, node.id)}`;
2611
+ }
2612
+ function moduleBodyText(state, node) {
2613
+ const body = node.body;
2614
+ if (body !== null) return ` ${capture(state, () => printTSModuleBlock(state, body))}`;
2615
+ return ";";
2616
+ }
2617
+ function printTSModuleBlock(state, node) {
2618
+ state.out += "{\n";
2619
+ state.out += indentedBodyText(state, node.body, (statement) => printStatement(state, statement));
2620
+ state.out += `${indent(state)}}`;
2621
+ }
2622
+ function printTSImportEqualsDeclaration(state, node) {
2623
+ state.out += `import ${flagText(node.importKind === "type", "type ")}${node.id.name} = ${moduleReferenceText(state, node.moduleReference)};`;
2624
+ }
2625
+ function moduleReferenceText(state, reference) {
2626
+ if (reference.type === "TSExternalModuleReference") return `require(${externalModuleArgumentText(reference.expression.value)})`;
2627
+ return sequenceNodeText(state, reference);
2628
+ }
2629
+ function printTSType(state, node) {
2630
+ state.out += printTSTypeToString(state, node);
2631
+ }
2632
+ function printTSTypeToString(state, node) {
2633
+ const saved = state.out;
2634
+ state.out = "";
2635
+ doPrintTSType(state, node);
2636
+ const result = state.out;
2637
+ state.out = saved;
2638
+ return result;
2639
+ }
2640
+ function doPrintTSType(state, node) {
2641
+ switch (node.type) {
2642
+ case "TSAnyKeyword":
2643
+ state.out += "any";
2644
+ break;
2645
+ case "TSStringKeyword":
2646
+ state.out += "string";
2647
+ break;
2648
+ case "TSBooleanKeyword":
2649
+ state.out += "boolean";
2650
+ break;
2651
+ case "TSNumberKeyword":
2652
+ state.out += "number";
2653
+ break;
2654
+ case "TSBigIntKeyword":
2655
+ state.out += "bigint";
2656
+ break;
2657
+ case "TSSymbolKeyword":
2658
+ state.out += "symbol";
2659
+ break;
2660
+ case "TSVoidKeyword":
2661
+ state.out += "void";
2662
+ break;
2663
+ case "TSUndefinedKeyword":
2664
+ state.out += "undefined";
2665
+ break;
2666
+ case "TSNullKeyword":
2667
+ state.out += "null";
2668
+ break;
2669
+ case "TSNeverKeyword":
2670
+ state.out += "never";
2671
+ break;
2672
+ case "TSUnknownKeyword":
2673
+ state.out += "unknown";
2674
+ break;
2675
+ case "TSObjectKeyword":
2676
+ state.out += "object";
2677
+ break;
2678
+ case "TSIntrinsicKeyword":
2679
+ state.out += "intrinsic";
2680
+ break;
2681
+ case "TSThisType":
2682
+ state.out += "this";
2683
+ break;
2684
+ case "TSTypeReference":
2685
+ printTSTypeName(state, node.typeName);
2686
+ state.out += typeArgumentsText(state, node.typeArguments);
2687
+ break;
2688
+ case "TSUnionType":
2689
+ state.out += tSTypeListText(state, node.types, " | ");
2690
+ break;
2691
+ case "TSIntersectionType":
2692
+ state.out += tSTypeListText(state, node.types, " & ");
2693
+ break;
2694
+ case "TSArrayType":
2695
+ state.out += `${arrayElementTypeText(state, node.elementType)}[]`;
2696
+ break;
2697
+ case "TSTypeLiteral":
2698
+ printTSTypeLiteral(state, node.members);
2699
+ break;
2700
+ case "TSTupleType":
2701
+ printTupleType(state, node.elementTypes);
2702
+ break;
2703
+ case "TSConditionalType":
2704
+ doPrintTSType(state, node.checkType);
2705
+ state.out += " extends ";
2706
+ doPrintTSType(state, node.extendsType);
2707
+ state.out += " ? ";
2708
+ doPrintTSType(state, node.trueType);
2709
+ state.out += " : ";
2710
+ doPrintTSType(state, node.falseType);
2711
+ break;
2712
+ case "TSInferType":
2713
+ state.out += `infer ${node.typeParameter.name.name}`;
2714
+ printTypeClause(state, " extends ", node.typeParameter.constraint);
2715
+ break;
2716
+ case "TSTypeQuery":
2717
+ state.out += "typeof ";
2718
+ printTypeQueryName(state, node);
2719
+ state.out += typeArgumentsText(state, node.typeArguments);
2720
+ break;
2721
+ case "TSImportType":
2722
+ printTSImportType(state, node);
2723
+ break;
2724
+ case "TSTypeOperator":
2725
+ state.out += `${node.operator} `;
2726
+ doPrintTSType(state, node.typeAnnotation);
2727
+ break;
2728
+ case "TSMappedType":
2729
+ printMappedType(state, node);
2730
+ break;
2731
+ case "TSTemplateLiteralType":
2732
+ printTSTemplateLiteral(state, node);
2733
+ break;
2734
+ case "TSFunctionType":
2735
+ printTSFunctionType(state, node);
2736
+ break;
2737
+ case "TSConstructorType":
2738
+ printTSConstructorType(state, node);
2739
+ break;
2740
+ case "TSTypePredicate":
2741
+ printTSTypePredicate(state, node);
2742
+ break;
2743
+ case "TSIndexedAccessType":
2744
+ doPrintTSType(state, node.objectType);
2745
+ state.out += "[";
2746
+ doPrintTSType(state, node.indexType);
2747
+ state.out += "]";
2748
+ break;
2749
+ case "TSNamedTupleMember":
2750
+ printNamedTupleMember(state, node);
2751
+ break;
2752
+ case "TSLiteralType":
2753
+ printTSLiteralType(state, node.literal);
2754
+ break;
2755
+ case "TSParenthesizedType":
2756
+ state.out += "(";
2757
+ doPrintTSType(state, node.typeAnnotation);
2758
+ state.out += ")";
2759
+ break;
2760
+ case "TSJSDocNullableType":
2761
+ printJSDocPostfixModifier(state, node, "?");
2762
+ break;
2763
+ case "TSJSDocNonNullableType":
2764
+ printJSDocPostfixModifier(state, node, "!");
2765
+ break;
2766
+ case "TSJSDocUnknownType": state.out += "?";
2767
+ }
2768
+ }
2769
+ function tSTypeListText(state, types, separator) {
2770
+ return types.map((type) => printTSTypeToString(state, type)).join(separator);
2771
+ }
2772
+ function arrayElementTypeText(state, type) {
2773
+ const printed = printTSTypeToString(state, type);
2774
+ if (ARRAY_ELEMENT_WRAPPED_KINDS[type.type] === true) return `(${printed})`;
2775
+ return printed;
2776
+ }
2777
+ function printTSTypeLiteral(state, members) {
2778
+ const rendered = members.map((member) => signatureText(state, member)).join("; ");
2779
+ switch (members.length) {
2780
+ case 0:
2781
+ state.out += "{}";
2782
+ break;
2783
+ default: state.out += `{ ${rendered} }`;
2784
+ }
2785
+ }
2786
+ function signatureText(state, member) {
2787
+ const printed = capture(state, () => printTSSignature(state, member));
2788
+ if (printed.endsWith(";")) return printed.slice(0, -1);
2789
+ return printed;
2790
+ }
2791
+ function printTupleType(state, elements) {
2792
+ state.out += `[${elements.map((element) => capture(state, () => printTupleElement(state, element))).join(", ")}]`;
2793
+ }
2794
+ function printTupleElement(state, element) {
2795
+ switch (nodeKind(element)) {
2796
+ case "TSRestType":
2797
+ printRestTupleElement(state, element);
2798
+ break;
2799
+ case "TSOptionalType":
2800
+ printOptionalTupleElement(state, element);
2801
+ break;
2802
+ case "TSNamedTupleMember":
2803
+ printNamedTupleElement(state, element);
2804
+ break;
2805
+ default: printTupleElementType(state, element);
2806
+ }
2807
+ }
2808
+ function printRestTupleElement(state, element) {
2809
+ if (isNodeOfKind(element, "TSRestType")) {
2810
+ state.out += "...";
2811
+ doPrintTSType(state, element.typeAnnotation);
2812
+ }
2813
+ }
2814
+ function printOptionalTupleElement(state, element) {
2815
+ if (isNodeOfKind(element, "TSOptionalType")) {
2816
+ doPrintTSType(state, element.typeAnnotation);
2817
+ state.out += "?";
2818
+ }
2819
+ }
2820
+ function printNamedTupleElement(state, element) {
2821
+ if (isNodeOfKind(element, "TSNamedTupleMember")) printNamedTupleMember(state, element);
2822
+ }
2823
+ function printTupleElementType(state, element) {
2824
+ if (isTSType(element)) doPrintTSType(state, element);
2825
+ }
2826
+ function printNamedTupleMember(state, member) {
2827
+ state.out += `${member.label.name}${flagText(member.optional, "?")}: `;
2828
+ printTupleElement(state, member.elementType);
2829
+ }
2830
+ function printTypeClause(state, keyword, type) {
2831
+ if (type == null) return;
2832
+ state.out += keyword;
2833
+ doPrintTSType(state, type);
2834
+ }
2835
+ function printTypeQueryName(state, node) {
2836
+ const exprName = node.exprName;
2837
+ if (exprName.type === "TSImportType") {
2838
+ doPrintTSType(state, exprName);
2839
+ return;
2840
+ }
2841
+ printTSTypeName(state, exprName);
2842
+ }
2843
+ function printTSTypeName(state, name) {
2844
+ if (name.type === "TSQualifiedName") {
2845
+ printTSTypeName(state, name.left);
2846
+ state.out += `.${name.right.name}`;
2847
+ return;
2848
+ }
2849
+ state.out += tSTypeNameLeafText(state, name);
2850
+ }
2851
+ function tSTypeNameLeafText(state, name) {
2852
+ switch (name.type) {
2853
+ case "Identifier": return name.name;
2854
+ case "ThisExpression": return "this";
2855
+ case "TSQualifiedName": return sequenceNodeText(state, name);
2856
+ }
2857
+ }
2858
+ function printTSImportTypeQualifier(state, qualifier) {
2859
+ if (qualifier === null) return;
2860
+ printTSImportTypeQualifierNode(state, qualifier);
2861
+ }
2862
+ function printTSImportTypeQualifierNode(state, qualifier) {
2863
+ if (qualifier.type === "Identifier") {
2864
+ state.out += qualifier.name;
2865
+ return;
2866
+ }
2867
+ printTSImportTypeQualifier(state, qualifier.left);
2868
+ state.out += `.${qualifier.right.name}`;
2869
+ }
2870
+ function printTSImportType(state, node) {
2871
+ printTSImportTypeSource(state, node);
2872
+ if (node.qualifier !== null) {
2873
+ state.out += ".";
2874
+ printTSImportTypeQualifier(state, node.qualifier);
2875
+ }
2876
+ state.out += typeArgumentsText(state, node.typeArguments);
2877
+ }
2878
+ function printTSImportTypeSource(state, node) {
2879
+ state.out += `import(${JSON.stringify(node.source.value)}`;
2880
+ state.out += flagText(node.options, `, ${assignmentNodeText(state, node.options)}`);
2881
+ state.out += ")";
2882
+ }
2883
+ function printMappedType(state, node) {
2884
+ state.out += "{ ";
2885
+ printMappedTypeModifier(state, node.readonly, "readonly ");
2886
+ state.out += `[${node.key.name} in `;
2887
+ doPrintTSType(state, node.constraint);
2888
+ printTypeClause(state, " as ", node.nameType);
2889
+ state.out += "]";
2890
+ printMappedTypeModifier(state, node.optional, "?");
2891
+ printTypeClause(state, ": ", node.typeAnnotation);
2892
+ state.out += " }";
2893
+ }
2894
+ function printMappedTypeModifier(state, modifier, rendered) {
2895
+ switch (modifier) {
2896
+ case true:
2897
+ state.out += rendered;
2898
+ break;
2899
+ case "+":
2900
+ state.out += `+${rendered}`;
2901
+ break;
2902
+ case "-": state.out += `-${rendered}`;
2898
2903
  }
2899
- printTSTypeParameterDeclaration(node) {
2900
- this.out += `<${node.params.map((param) => this.capture(() => this.printTSTypeParameter(param))).join(", ")}>`;
2904
+ }
2905
+ function printTSTemplateLiteral(state, node) {
2906
+ state.out += `\`${node.quasis.map((quasi, index) => templateTypeQuasiText(state, quasi, node.types[index])).join("")}\``;
2907
+ }
2908
+ function templateTypeQuasiText(state, quasi, type) {
2909
+ switch (quasi.tail) {
2910
+ case true: return quasi.value.raw;
2911
+ case false: return templateTypeText(state, quasi, type);
2901
2912
  }
2902
- printTSTypeParameterInstantiation(node) {
2903
- this.out += `<${node.params.map((param) => this.printTSTypeToString(param)).join(", ")}>`;
2913
+ }
2914
+ function templateTypeText(state, quasi, type) {
2915
+ if (type === void 0) throw new Error("Printer: template literal type has no type for its quasi");
2916
+ return `${quasi.value.raw}\${${printTSTypeToString(state, type)}}`;
2917
+ }
2918
+ function printTSFunctionType(state, node) {
2919
+ state.out += `${typeParametersText(state, node.typeParameters)}(${paramsText(state, node.params)}) => ${printTSTypeToString(state, node.returnType.typeAnnotation)}`;
2920
+ }
2921
+ function printTSConstructorType(state, node) {
2922
+ state.out += `${flagText(node.abstract, "abstract ")}new ${typeParametersText(state, node.typeParameters)}(${paramsText(state, node.params)}) => ${printTSTypeToString(state, node.returnType.typeAnnotation)}`;
2923
+ }
2924
+ function printTSTypePredicate(state, node) {
2925
+ state.out += flagText(node.asserts, "asserts ");
2926
+ state.out += typePredicateParameterText(node.parameterName);
2927
+ printPredicateAnnotation(state, node);
2928
+ }
2929
+ function printPredicateAnnotation(state, node) {
2930
+ if (node.typeAnnotation === null) return;
2931
+ printTypeClause(state, " is ", node.typeAnnotation.typeAnnotation);
2932
+ }
2933
+ function printTSLiteralType(state, literal) {
2934
+ switch (literal.type) {
2935
+ case "Literal":
2936
+ printLiteral(state, literal);
2937
+ return;
2938
+ case "TemplateLiteral":
2939
+ printTemplateLiteral(state, literal);
2940
+ return;
2941
+ case "UnaryExpression": printTSLiteralUnary(state, literal);
2904
2942
  }
2905
- printTSTypeParameter(node) {
2906
- this.out += typeParameterModifiersText(node);
2907
- this.out += node.name.name;
2908
- this.printTypeClause(" extends ", node.constraint);
2909
- this.printTypeClause(" = ", node.default);
2943
+ }
2944
+ function printTSLiteralUnary(state, unary) {
2945
+ state.out += unary.operator;
2946
+ if (isLiteralNode(unary.argument)) printLiteral(state, unary.argument);
2947
+ }
2948
+ function printJSDocPostfixModifier(state, node, marker) {
2949
+ if (node.postfix) {
2950
+ doPrintTSType(state, node.typeAnnotation);
2951
+ state.out += marker;
2952
+ return;
2910
2953
  }
2911
- };
2954
+ state.out += marker;
2955
+ doPrintTSType(state, node.typeAnnotation);
2956
+ }
2957
+ function printTSTypeAnnotation(state, node) {
2958
+ state.out += ": ";
2959
+ doPrintTSType(state, node.typeAnnotation);
2960
+ }
2961
+ function printTSTypeParameterDeclaration(state, node) {
2962
+ state.out += `<${node.params.map((param) => capture(state, () => printTSTypeParameter(state, param))).join(", ")}>`;
2963
+ }
2964
+ function printTSTypeParameterInstantiation(state, node) {
2965
+ state.out += `<${node.params.map((param) => printTSTypeToString(state, param)).join(", ")}>`;
2966
+ }
2967
+ function printTSTypeParameter(state, node) {
2968
+ state.out += typeParameterModifiersText(node);
2969
+ state.out += node.name.name;
2970
+ printTypeClause(state, " extends ", node.constraint);
2971
+ printTypeClause(state, " = ", node.default);
2972
+ }
2912
2973
  const TS_TYPE_NODE_KINDS = {
2913
2974
  TSAnyKeyword: true,
2914
2975
  TSStringKeyword: true,
@@ -2953,13 +3014,65 @@ const TS_TYPE_NODE_KINDS = {
2953
3014
  function isTSTypeNode(kind) {
2954
3015
  return TS_TYPE_NODE_KINDS[kind] === true;
2955
3016
  }
3017
+ function isTSType(node) {
3018
+ return isTSTypeNode(node.type);
3019
+ }
3020
+ function isNodeOfKind(node, kind) {
3021
+ return node.type === kind;
3022
+ }
3023
+ const FUNCTION_KINDS = {
3024
+ FunctionDeclaration: true,
3025
+ FunctionExpression: true,
3026
+ TSDeclareFunction: true,
3027
+ TSEmptyBodyFunctionExpression: true
3028
+ };
3029
+ function isFunctionNode(node) {
3030
+ return FUNCTION_KINDS[node.type] === true;
3031
+ }
3032
+ function isAssignmentPattern(node) {
3033
+ return node.type === "AssignmentPattern";
3034
+ }
3035
+ function isLiteralNode(node) {
3036
+ return node.type === "Literal";
3037
+ }
3038
+ const ABSENT_NODE_KIND = "\0absent";
3039
+ function nodeKind(node) {
3040
+ if (node == null) return ABSENT_NODE_KIND;
3041
+ return node.type;
3042
+ }
3043
+ function isIdentifierNode(node) {
3044
+ if (node == null) return false;
3045
+ return node.type === "Identifier";
3046
+ }
3047
+ function isPrivateIdentifierNode(node) {
3048
+ if (node == null) return false;
3049
+ return node.type === "PrivateIdentifier";
3050
+ }
3051
+ function isAssignmentPatternNode(node) {
3052
+ if (node == null) return false;
3053
+ return node.type === "AssignmentPattern";
3054
+ }
3055
+ function identifierName(node) {
3056
+ if (isIdentifierNode(node)) return node.name;
3057
+ }
3058
+ function identifierNameText(node) {
3059
+ return identifierName(node) ?? "";
3060
+ }
3061
+ function privateIdentifierText(node) {
3062
+ if (isPrivateIdentifierNode(node)) return `#${node.name}`;
3063
+ return "";
3064
+ }
3065
+ function literalCapture(state, node) {
3066
+ if (isLiteralNode(node)) return capture(state, () => printLiteral(state, node));
3067
+ return capture(state, () => printNodePrec(state, node, PREC.Assignment));
3068
+ }
2956
3069
  function precOf(node) {
2957
- switch (node.type) {
3070
+ switch (nodeKind(node)) {
2958
3071
  case "SequenceExpression": return PREC.Sequence;
2959
3072
  case "AssignmentExpression": return PREC.Assignment;
2960
3073
  case "ConditionalExpression": return PREC.Conditional;
2961
- case "LogicalExpression": return logicalPrec(node.operator);
2962
- case "BinaryExpression": return binaryPrec(node.operator);
3074
+ case "LogicalExpression": return logicalPrecOf(node);
3075
+ case "BinaryExpression": return binaryPrecOf(node);
2963
3076
  case "UnaryExpression":
2964
3077
  case "AwaitExpression":
2965
3078
  case "YieldExpression": return PREC.Unary;
@@ -2973,6 +3086,14 @@ function precOf(node) {
2973
3086
  default: return PREC.Primary;
2974
3087
  }
2975
3088
  }
3089
+ function logicalPrecOf(node) {
3090
+ if (node.type === "LogicalExpression") return logicalPrec(node.operator);
3091
+ return PREC.Primary;
3092
+ }
3093
+ function binaryPrecOf(node) {
3094
+ if (node.type === "BinaryExpression") return binaryPrec(node.operator);
3095
+ return PREC.Primary;
3096
+ }
2976
3097
  const EVERY_COMMENT_POSITION = Number.POSITIVE_INFINITY;
2977
3098
  const END_OF_COMMENTS = {
2978
3099
  type: "Line",
@@ -2984,52 +3105,9 @@ function sortedCommentsWithoutHashbang(comments, hashbang) {
2984
3105
  return [...withoutHashbangComment(comments ?? [], hashbang)].sort((a, b) => a.start - b.start);
2985
3106
  }
2986
3107
  function withoutHashbangComment(comments, hashbang) {
2987
- switch (hashbang) {
2988
- case null: return comments;
2989
- default: {
2990
- const { start } = hashbang;
2991
- return comments.filter((comment) => !(comment.type === "Line" && comment.start === start));
2992
- }
2993
- }
2994
- }
2995
- const ABSENT_NODE_KIND = "\0absent";
2996
- const ABSENT_NODE = { type: ABSENT_NODE_KIND };
2997
- function nodeKind(node) {
2998
- return (node ?? ABSENT_NODE).type;
2999
- }
3000
- function propertyForm(fields) {
3001
- switch (true) {
3002
- case fields.kind === "get":
3003
- case fields.kind === "set": return "accessor";
3004
- case fields.method === true: return "method";
3005
- case isShorthandMatch(fields): return "shorthand";
3006
- case isShorthandDefaultMatch(fields): return "shorthandDefault";
3007
- default: return "verbose";
3008
- }
3009
- }
3010
- function isShorthandMatch(fields) {
3011
- return fields.shorthand === true && namesMatch(identifierName(fields.key), identifierName(fields.value));
3012
- }
3013
- function isShorthandDefaultMatch(fields) {
3014
- return fields.shorthand === true && namesMatch(identifierName(fields.key), defaultTargetName(fields.value));
3015
- }
3016
- function identifierName(node) {
3017
- switch (nodeKind(node)) {
3018
- case "Identifier": return node.name;
3019
- default: return;
3020
- }
3021
- }
3022
- function defaultTargetName(node) {
3023
- switch (nodeKind(node)) {
3024
- case "AssignmentPattern": return identifierName(node.left);
3025
- default: return;
3026
- }
3027
- }
3028
- function namesMatch(key, value) {
3029
- switch (value) {
3030
- case void 0: return false;
3031
- default: return key === value;
3032
- }
3108
+ if (hashbang === null) return comments;
3109
+ const { start } = hashbang;
3110
+ return comments.filter((comment) => !(comment.type === "Line" && comment.start === start));
3033
3111
  }
3034
3112
  const MEMBER_OBJECT_WRAPPED_KINDS = {
3035
3113
  SequenceExpression: true,
@@ -3057,41 +3135,64 @@ const UNARY_WORD_OPERATORS = {
3057
3135
  void: true,
3058
3136
  delete: true
3059
3137
  };
3138
+ const ARRAY_ELEMENT_WRAPPED_KINDS = {
3139
+ TSUnionType: true,
3140
+ TSIntersectionType: true
3141
+ };
3060
3142
  function parenthesizedIf(wrap, text) {
3061
- switch (wrap) {
3062
- case true: return `(${text})`;
3063
- default: return text;
3064
- }
3143
+ if (wrap) return `(${text})`;
3144
+ return text;
3065
3145
  }
3066
3146
  function jsxAttributeNameText(name) {
3067
- switch (name.type) {
3068
- case "JSXIdentifier": return name.name;
3069
- default: return `${name.namespace.name}:${name.name.name}`;
3070
- }
3147
+ if (name.type === "JSXIdentifier") return name.name;
3148
+ return `${name.namespace.name}:${name.name.name}`;
3071
3149
  }
3072
- const BARE_DEFAULT_EXPORT_KINDS = {
3073
- FunctionDeclaration: true,
3074
- ClassDeclaration: true,
3075
- TSInterfaceDeclaration: true
3076
- };
3077
- const ARRAY_ELEMENT_WRAPPED_KINDS = {
3078
- TSUnionType: true,
3079
- TSIntersectionType: true
3150
+ function propertyForm(fields) {
3151
+ if (isAccessorKind(fields)) return "accessor";
3152
+ return propertyFormWithoutAccessor(fields);
3153
+ }
3154
+ function isAccessorKind(fields) {
3155
+ return fields.kind === "get" || fields.kind === "set";
3156
+ }
3157
+ function propertyFormWithoutAccessor(fields) {
3158
+ if (fields.method === true) return "method";
3159
+ return propertyFormShorthand(fields);
3160
+ }
3161
+ function propertyFormShorthand(fields) {
3162
+ if (isShorthandMatch(fields)) return "shorthand";
3163
+ return propertyFormDefault(fields);
3164
+ }
3165
+ function propertyFormDefault(fields) {
3166
+ if (isShorthandDefaultMatch(fields)) return "shorthandDefault";
3167
+ return "verbose";
3168
+ }
3169
+ function isShorthandMatch(fields) {
3170
+ return fields.shorthand === true && namesMatch(identifierName(fields.key), identifierName(fields.value));
3171
+ }
3172
+ function isShorthandDefaultMatch(fields) {
3173
+ return fields.shorthand === true && namesMatch(identifierName(fields.key), defaultTargetName(fields.value));
3174
+ }
3175
+ function defaultTargetName(node) {
3176
+ if (isAssignmentPatternNode(node)) return identifierName(node.left);
3177
+ }
3178
+ function namesMatch(key, value) {
3179
+ if (value === void 0) return false;
3180
+ return key === value;
3181
+ }
3182
+ const BINDING_TYPE_ANNOTATION_KINDS = {
3183
+ Identifier: true,
3184
+ ObjectPattern: true,
3185
+ ArrayPattern: true
3080
3186
  };
3081
- function typeParameterModifiersText(node) {
3082
- return `${flagText(node.in, "in ")}${flagText(node.out, "out ")}${flagText(node.const, "const ")}`;
3187
+ function bindingTypeAnnotation(node) {
3188
+ if (isBindingTypeAnnotationCarrier(node)) return node.typeAnnotation;
3083
3189
  }
3084
- function typePredicateParameterText(parameterName) {
3085
- switch (parameterName.type) {
3086
- case "TSThisType": return "this";
3087
- default: return parameterName.name;
3088
- }
3190
+ function isBindingTypeAnnotationCarrier(node) {
3191
+ return BINDING_TYPE_ANNOTATION_KINDS[node.type] === true;
3089
3192
  }
3090
- function externalModuleArgumentText(value) {
3091
- switch (Boolean(value)) {
3092
- case true: return JSON.stringify(value);
3093
- default: return "\"\"";
3094
- }
3193
+ function bindingNameText(node) {
3194
+ if (node.name === void 0) return "";
3195
+ return node.name;
3095
3196
  }
3096
3197
  const EXPORT_NAME_TEXTS = {
3097
3198
  Identifier: (name) => name.name ?? "",
@@ -3126,32 +3227,31 @@ function namedSpecifierText(specifier) {
3126
3227
  return `${flagText(specifier.importKind === "type", "type ")}${alias}`;
3127
3228
  }
3128
3229
  function importLocalName(specifier) {
3129
- switch (nodeKind(specifier)) {
3130
- case ABSENT_NODE_KIND: return "";
3131
- default: return specifier.local.name;
3132
- }
3230
+ if (specifier === void 0) return "";
3231
+ return specifier.local.name;
3133
3232
  }
3134
3233
  function importedNameText(imported) {
3135
- switch (nodeKind(imported)) {
3136
- case "Identifier": return imported.name;
3137
- default: return imported.value;
3138
- }
3234
+ if (imported === void 0) return "";
3235
+ return importedNameOf(imported);
3236
+ }
3237
+ function importedNameOf(imported) {
3238
+ if (imported.type === "Identifier") return nameOrEmpty(imported.name);
3239
+ return nameOrEmpty(imported.value);
3240
+ }
3241
+ function nameOrEmpty(value) {
3242
+ return value ?? "";
3139
3243
  }
3140
3244
  function exportAliasText(localName, exportedName) {
3141
- switch (localName === exportedName) {
3142
- case true: return localName;
3143
- default: return `${localName} as ${exportedName}`;
3144
- }
3245
+ if (localName === exportedName) return localName;
3246
+ return `${localName} as ${exportedName}`;
3145
3247
  }
3146
3248
  function exportSpecifierText(specifier) {
3147
3249
  const alias = exportAliasText(exportNameToString(specifier.local), exportNameToString(specifier.exported));
3148
3250
  return `${flagText(specifier.exportKind === "type", "type ")}${alias}`;
3149
3251
  }
3150
3252
  function exportedNameClauseText(exported) {
3151
- switch (nodeKind(exported)) {
3152
- case ABSENT_NODE_KIND: return "";
3153
- default: return ` as ${exportNameToString(exported)}`;
3154
- }
3253
+ if (exported == null) return "";
3254
+ return ` as ${exportNameToString(exported)}`;
3155
3255
  }
3156
3256
  function importAttributesText(attrs) {
3157
3257
  const rendered = attrs.map((attribute) => importAttributeText(attribute)).join(", ");
@@ -3161,17 +3261,13 @@ function importAttributeText(attribute) {
3161
3261
  return `${importAttrKeyText(attribute.key)}: ${JSON.stringify(attribute.value.value)}`;
3162
3262
  }
3163
3263
  function importAttrKeyText(key) {
3164
- switch (key.type) {
3165
- case "Identifier": return key.name;
3166
- default: return JSON.stringify(key.value);
3167
- }
3264
+ if (key.type === "Identifier") return key.name;
3265
+ return JSON.stringify(key.value);
3168
3266
  }
3169
3267
  function bareArrowParamName(node) {
3170
3268
  const name = singleParamName(node);
3171
- switch (name) {
3172
- case "": return "";
3173
- default: return flagText(node.returnType == null, name);
3174
- }
3269
+ if (name === "") return "";
3270
+ return flagText(node.returnType == null, name);
3175
3271
  }
3176
3272
  function singleParamName(node) {
3177
3273
  switch (node.params.length) {
@@ -3180,49 +3276,33 @@ function singleParamName(node) {
3180
3276
  }
3181
3277
  }
3182
3278
  function bareParameterName(param) {
3183
- const fields = param;
3184
- switch (true) {
3185
- case fields === void 0: return "";
3186
- case fields.type !== "Identifier": return "";
3187
- case fields.typeAnnotation != null: return "";
3188
- case fields.name === void 0: return "";
3189
- default: return fields.name;
3190
- }
3279
+ if (param === void 0) return "";
3280
+ return bareParameterNameOf(param);
3281
+ }
3282
+ function bareParameterNameOf(param) {
3283
+ if (!isUnannotatedIdentifier(param)) return "";
3284
+ return param.name;
3285
+ }
3286
+ function isUnannotatedIdentifier(param) {
3287
+ if (param.type !== "Identifier") return false;
3288
+ return param.typeAnnotation == null;
3191
3289
  }
3192
3290
  function arrowBodyIsBlock(body) {
3193
- return nodeKind(body) === "BlockStatement";
3291
+ return body.type === "BlockStatement";
3194
3292
  }
3195
3293
  function functionHeaderText(node) {
3196
3294
  return `${flagText(node.declare, "declare ")}${flagText(node.async, "async ")}function${flagText(node.generator, "*")}${namedDeclarationText(node)}`;
3197
3295
  }
3198
3296
  function namedDeclarationText(node) {
3199
- switch (Boolean(node.id)) {
3200
- case true: return ` ${node.id.name}`;
3201
- default: return "";
3202
- }
3203
- }
3204
- function bindingNameText(node) {
3205
- switch (node.name) {
3206
- case void 0: return "";
3207
- default: return node.name;
3208
- }
3209
- }
3210
- function parameterForm(param) {
3211
- switch (true) {
3212
- case param["type"] === "RestElement": return "rest";
3213
- case param["type"] === "TSParameterProperty": return "property";
3214
- default: return "formal";
3215
- }
3297
+ if (node.id == null) return "";
3298
+ return ` ${node.id.name}`;
3216
3299
  }
3217
3300
  function parameterPropertyModifiers(param) {
3218
- const accessibility = param["accessibility"];
3219
- return `${flagText(accessibility, `${accessibility} `)}${flagText(param["readonly"], "readonly ")}${flagText(param["override"], "override ")}${flagText(param["static"], "static ")}`;
3301
+ return `${flagText(param.accessibility, `${param.accessibility} `)}${flagText(param.readonly, "readonly ")}${flagText(param.override, "override ")}${flagText(param.static, "static ")}`;
3220
3302
  }
3221
3303
  function commentText(comment) {
3222
- switch (comment.type) {
3223
- case "Block": return `/*${comment.value}*/`;
3224
- default: return `//${comment.value}`;
3225
- }
3304
+ if (comment.type === "Block") return `/*${comment.value}*/`;
3305
+ return `//${comment.value}`;
3226
3306
  }
3227
3307
  function methodDefinitionPrefix(node, fn) {
3228
3308
  return `${flagText(node.accessibility, `${node.accessibility} `)}${flagText(node.static, "static ")}${flagText(node.override, "override ")}${flagText(fn.async, "async ")}${flagText(fn.generator, "*")}${methodKindText(node.kind)}`;
@@ -3238,28 +3318,56 @@ function propertyDefinitionModifiers(node) {
3238
3318
  return `${flagText(node.declare, "declare ")}${flagText(node.accessibility, `${node.accessibility} `)}${flagText(node.static, "static ")}${flagText(node.readonly, "readonly ")}${flagText(node.override, "override ")}`;
3239
3319
  }
3240
3320
  function literalText(node) {
3241
- switch (true) {
3242
- case node.raw != null: return node.raw;
3243
- case node.regex != null: return `/${node.regex.pattern}/${node.regex.flags}`;
3244
- case node.bigint != null: return node.bigint;
3245
- default: return valueLiteralText(node.value);
3246
- }
3321
+ if (node.raw != null) return node.raw;
3322
+ return literalWithoutRaw(node);
3323
+ }
3324
+ function literalWithoutRaw(node) {
3325
+ if (node.regex != null) return `/${node.regex.pattern}/${node.regex.flags}`;
3326
+ return literalWithoutRegex(node);
3327
+ }
3328
+ function literalWithoutRegex(node) {
3329
+ if (node.bigint != null) return node.bigint;
3330
+ return valueLiteralText(node.value);
3247
3331
  }
3248
3332
  function valueLiteralText(value) {
3249
3333
  switch (typeof value) {
3250
3334
  case "string": return JSON.stringify(value);
3251
- case "number":
3335
+ case "number": return String(value);
3252
3336
  case "boolean": return String(value);
3253
3337
  case "bigint": return `${value}n`;
3254
- default: return "null";
3338
+ case "symbol":
3339
+ case "undefined":
3340
+ case "object":
3341
+ case "function": return "null";
3255
3342
  }
3256
3343
  }
3257
3344
  function flagText(present, text) {
3258
3345
  switch (Boolean(present)) {
3259
3346
  case true: return text;
3260
- default: return "";
3347
+ case false: return "";
3348
+ }
3349
+ }
3350
+ function typeParameterModifiersText(node) {
3351
+ return `${flagText(node.in, "in ")}${flagText(node.out, "out ")}${flagText(node.const, "const ")}`;
3352
+ }
3353
+ function typePredicateParameterText(parameterName) {
3354
+ if (parameterName.type === "TSThisType") return "this";
3355
+ return parameterName.name;
3356
+ }
3357
+ function externalModuleArgumentText(value) {
3358
+ switch (Boolean(value)) {
3359
+ case true: return JSON.stringify(value);
3360
+ case false: return "\"\"";
3261
3361
  }
3262
3362
  }
3363
+ const BARE_DEFAULT_EXPORT_KINDS = {
3364
+ FunctionDeclaration: true,
3365
+ ClassDeclaration: true,
3366
+ TSInterfaceDeclaration: true
3367
+ };
3368
+ function isBareDefaultExport(node) {
3369
+ return BARE_DEFAULT_EXPORT_KINDS[node.type] === true;
3370
+ }
3263
3371
  //#endregion
3264
3372
  //#region src/Printer.ts
3265
3373
  /**
@@ -3342,6 +3450,76 @@ function appendStatement(state, script, rawContent, context) {
3342
3450
  };
3343
3451
  }
3344
3452
  //#endregion
3453
+ //#region src/Mutant.ts
3454
+ const isMutant = (value) => S.is(Mutant)(value);
3455
+ const INSTRUMENTER_CONSTANTS = Object.freeze({
3456
+ NAMESPACE: "__stryker__",
3457
+ MUTATION_COVERAGE_OBJECT: "mutantCoverage",
3458
+ ACTIVE_MUTANT: "activeMutant",
3459
+ CURRENT_TEST_ID: "currentTestId",
3460
+ HIT_COUNT: "hitCount",
3461
+ HIT_LIMIT: "hitLimit",
3462
+ ACTIVE_MUTANT_ENV_VARIABLE: "__STRYKER_ACTIVE_MUTANT__"
3463
+ });
3464
+ function normalizeFileName(fileName) {
3465
+ return fileName.replace(/\\/g, "/");
3466
+ }
3467
+ const hasText = (value) => Predicate.isString(value) && value.length > 0;
3468
+ const textIfNonEmpty = (value) => Option.getOrUndefined(Option.filter(Option.fromUndefinedOr(value), hasText));
3469
+ const fieldOf = (value, key) => Match.value(key in value).pipe(Match.when(true, () => {
3470
+ return Reflect.get(value, key);
3471
+ }), Match.orElse(() => void 0));
3472
+ const hasStringCode = (error) => Match.value(fieldOf(error, "code")).pipe(Match.when(Match.string, () => true), Match.orElse(() => false));
3473
+ function isErrnoException(error) {
3474
+ return Match.value(error).pipe(Match.when(Match.instanceOf(Error), hasStringCode), Match.orElse(() => false));
3475
+ }
3476
+ const isEmptyNumber = (value) => Match.value(value).pipe(Match.when(0, () => true), Match.orElse(Number.isNaN));
3477
+ const isEmptyError = (error) => Match.value(error).pipe(Match.when(Match.undefined, () => true), Match.when(Match.null, () => true), Match.when(Match.string, (text) => text.length === 0), Match.when(Match.number, isEmptyNumber), Match.when(Match.boolean, (value) => !value), Match.orElse(() => false));
3478
+ const formatErrnoException = (error) => Match.value(error.stack).pipe(Match.when(hasText, (stack) => `${error.name}: ${error.code} (${error.syscall}) ${stack}`), Match.orElse(() => `${error.name}: ${error.code} (${error.syscall})`));
3479
+ const formatError = (error) => Match.value(error.stack).pipe(Match.when(hasText, (stack) => `${error.name}: ${error.message}\n${stack}`), Match.orElse(() => `${error.name}: ${error.message}`));
3480
+ const isJsonPrimitive = (value) => Match.value(value).pipe(Match.when(Match.number, () => true), Match.when(Match.boolean, () => true), Match.when(Match.bigint, () => true), Match.orElse(() => false));
3481
+ const jsonText = (error) => {
3482
+ try {
3483
+ return textIfNonEmpty(JSON.stringify(error));
3484
+ } catch {
3485
+ return;
3486
+ }
3487
+ };
3488
+ const isNonPlaceholderText = (text) => Match.value({
3489
+ hasLength: text.length > 0,
3490
+ isPlaceholder: text === "[object Object]"
3491
+ }).pipe(Match.when({
3492
+ hasLength: true,
3493
+ isPlaceholder: false
3494
+ }, () => true), Match.orElse(() => false));
3495
+ const isUsableText = (value) => Match.value(value).pipe(Match.when(Match.string, isNonPlaceholderText), Match.orElse(() => false));
3496
+ const usableText = (value) => Match.value(value).pipe(Match.when(isUsableText, (text) => text), Match.orElse(() => ""));
3497
+ const objectToStringText = (value) => Match.value(fieldOf(value, "toString")).pipe(Match.when(Match.instanceOf(Function), (callable) => {
3498
+ try {
3499
+ return usableText(Reflect.apply(callable, value, []));
3500
+ } catch {
3501
+ return "";
3502
+ }
3503
+ }), Match.orElse(() => ""));
3504
+ const isObjectType = (cause) => typeof cause === "object";
3505
+ const toStringText = (error) => Match.value(error).pipe(Match.when(Match.null, () => ""), Match.when(isObjectType, (value) => objectToStringText(value)), Match.orElse(() => ""));
3506
+ const stringifyRest = (error) => Match.value(jsonText(error)).pipe(Match.when(hasText, (json) => json), Match.orElse(() => toStringText(error)));
3507
+ const stringifyNonError = (error) => Match.value(error).pipe(Match.when(Match.string, (text) => text), Match.when(isJsonPrimitive, (primitive) => JSON.stringify(primitive)), Match.orElse(() => stringifyRest(error)));
3508
+ const errorText = (error) => Match.value(error).pipe(Match.when(isErrnoException, formatErrnoException), Match.orElse(() => formatError(error)));
3509
+ function errorToString(error) {
3510
+ return Match.value(error).pipe(Match.when(isEmptyError, () => ""), Match.when(Match.instanceOf(Error), errorText), Match.orElse(() => stringifyNonError(error)));
3511
+ }
3512
+ const ERROR_CODES = Object.freeze({ NoSuchFileOrDirectory: "ENOENT" });
3513
+ const errorNameOf = (value) => Match.value(value).pipe(Match.when(Match.instanceOf(Error), (error) => textIfNonEmpty(error.name)), Match.orElse(() => void 0));
3514
+ const tagOf = (value) => Match.value(textIfNonEmpty(fieldOf(value, "_tag"))).pipe(Match.when(hasText, (tag) => tag), Match.orElse(() => errorNameOf(value)));
3515
+ const textWithNested = (own, nested) => Match.value(own).pipe(Match.when(hasText, (text) => appendNested(text, nested)), Match.orElse(() => nested));
3516
+ const appendNested = (own, nested) => Match.value(nested).pipe(Match.when(hasText, (text) => `${own}: ${text}`), Match.orElse(() => own));
3517
+ const errorMessage = (error) => Match.value(error.message.length > 0).pipe(Match.when(true, () => error.message), Match.orElse(() => tagOf(error)));
3518
+ const errorMessageOrTag = (value) => Match.value(value).pipe(Match.when(Match.instanceOf(Error), errorMessage), Match.orElse(() => tagOf(value)));
3519
+ const messageText = (value) => Match.value(textIfNonEmpty(fieldOf(value, "message"))).pipe(Match.when(hasText, (message) => message), Match.orElse(() => errorMessageOrTag(value)));
3520
+ const ownCauseText = (value) => Match.value(textIfNonEmpty(fieldOf(value, "reason"))).pipe(Match.when(hasText, (reason) => reason), Match.orElse(() => messageText(value)));
3521
+ const causeText = (cause, depth) => Match.value(cause).pipe(Match.when(() => depth > 4, () => void 0), Match.when(Match.undefined, () => void 0), Match.when(Match.null, () => void 0), Match.when(Match.string, textIfNonEmpty), Match.when(isObjectType, (value) => textWithNested(ownCauseText(value), causeText(fieldOf(value, "cause"), depth + 1))), Match.orElse(() => void 0));
3522
+ //#endregion
3345
3523
  //#region src/Mutator.ts
3346
3524
  /**
3347
3525
  * Mutator — every mutation operator and its registry.
@@ -4062,7 +4240,9 @@ function regexFlags(parent) {
4062
4240
  const PLACEHOLDER = "Stryker was here!";
4063
4241
  const stringLiteralMutator = (node, context) => Match.value(node).pipe(Match.when(isTemplateLiteral, (template) => templateMutants(template)), Match.when(isStringLiteral, (literal) => mutantsWhen(isValidParent(literal, context), () => [stringLiteral(replacementText(literal.value.length === 0))])), Match.orElse(() => NO_MUTANTS));
4064
4242
  function templateMutants(template) {
4065
- return Match.value(template.quasis[0]).pipe(Match.when(void 0, () => NO_MUTANTS), Match.orElse((first) => [emptyOrPlaceholderTemplate(template, first)]));
4243
+ const first = template.quasis[0];
4244
+ if (first === void 0) return NO_MUTANTS;
4245
+ return [emptyOrPlaceholderTemplate(template, first)];
4066
4246
  }
4067
4247
  function emptyOrPlaceholderTemplate(template, first) {
4068
4248
  return templateLiteral([templateElement(replacementText([template.quasis.length === 1, first.value.raw.length === 0].every(Boolean)))], []);
@@ -4252,7 +4432,13 @@ function processStrykerDirectives(rule, node, allMutatorNames, originFileName) {
4252
4432
  };
4253
4433
  }
4254
4434
  function attachedComments(node) {
4255
- return node.leadingComments ?? NO_COMMENTS;
4435
+ return leadingCommentsOn(node) ?? NO_COMMENTS;
4436
+ }
4437
+ function leadingCommentsOn(value) {
4438
+ if (isCommentBearing(value)) return value.leadingComments;
4439
+ }
4440
+ function isCommentBearing(value) {
4441
+ return Predicate.hasProperty(value, "leadingComments");
4256
4442
  }
4257
4443
  /** A comment that matched the directive grammar, decoded into the fields a rule needs. */
4258
4444
  function parseStrykerDirective(comment) {
@@ -4368,16 +4554,35 @@ function mutationCoverageSequenceExpression(mutants, targetExpression) {
4368
4554
  return sequenceExpression(sequence);
4369
4555
  }
4370
4556
  function nodeOfKind(mutant, node, isKind, kind) {
4371
- if (!isKind(node)) throw new Error(`Cannot place mutant ${mutant.id}: expected ${kind}, got ${node.type}`);
4372
- return node;
4557
+ return narrowNode(node, isKind, `Cannot place mutant ${mutant.id}: expected ${kind}, got ${node.type}`);
4558
+ }
4559
+ function narrowNode(node, isKind, message) {
4560
+ if (isKind(node)) return node;
4561
+ throw new Error(message);
4562
+ }
4563
+ function expressionOf(node) {
4564
+ return narrowNode(node, isExpressionKind, `Expected an expression, got ${node.type}`);
4565
+ }
4566
+ function statementOf(node) {
4567
+ return narrowNode(node, isStatementKind, `Expected a statement, got ${node.type}`);
4568
+ }
4569
+ function isSwitchCase(node) {
4570
+ return nodeType(node) === "SwitchCase";
4571
+ }
4572
+ function switchCaseOf(node) {
4573
+ return narrowNode(node, isSwitchCase, `Expected a switch case, got ${node.type}`);
4373
4574
  }
4374
4575
  function throwPlacementError(error, nodePath, placer, mutants, fileName, lineTable, basePath) {
4375
4576
  const message = `${placer.name} could not place mutants with type(s): "${placementListFormat.format(mutants.map((mutant) => mutant.mutatorName))}"`;
4376
4577
  const errorMessage = `${placementLocation(nodePath.node, fileName, lineTable, basePath)} ${message}. Either remove this file from the list of files to be mutated, or exclude the mutator (using \`mutator.excludedMutations\`). Original error: ${error.stack}`;
4377
4578
  throw new Error(errorMessage);
4378
4579
  }
4580
+ const fileNameWithin = (basePath, fileName) => {
4581
+ if (basePath === void 0) return fileName;
4582
+ return relativeTo(basePath, fileName);
4583
+ };
4379
4584
  function placementLocation(node, fileName, lineTable, basePath) {
4380
- const relativeFile = basePath === void 0 ? fileName : relativeTo(basePath, fileName);
4585
+ const relativeFile = fileNameWithin(basePath, fileName);
4381
4586
  const position = Option.map(Option.fromNullishOr(spanOf(node)), (span) => positionFromLineTable(span.start, lineTable));
4382
4587
  return Option.match(position, {
4383
4588
  onNone: () => `${relativeFile}:undefined:undefined`,
@@ -4388,12 +4593,14 @@ const placementListFormat = new Intl.ListFormat("en");
4388
4593
  const normalizeSeparators = (value) => value.replace(/\\/g, "/");
4389
4594
  const withTrailingSlash = (basePath) => {
4390
4595
  const normalized = normalizeSeparators(basePath);
4391
- return normalized.endsWith("/") ? normalized : `${normalized}/`;
4596
+ if (normalized.endsWith("/")) return normalized;
4597
+ return `${normalized}/`;
4392
4598
  };
4393
4599
  const relativeTo = (basePath, fileName) => {
4394
4600
  const prefix = withTrailingSlash(basePath);
4395
4601
  const normalizedFile = normalizeSeparators(fileName);
4396
- return normalizedFile.startsWith(prefix) ? normalizedFile.slice(prefix.length) : fileName;
4602
+ if (!normalizedFile.startsWith(prefix)) return fileName;
4603
+ return normalizedFile.slice(prefix.length);
4397
4604
  };
4398
4605
  function classOrFunctionExpressionNamedIfNeeded(path) {
4399
4606
  return Match.value(path.node).pipe(Match.when(isAnonymousFunctionOrClass, (node) => nameFromParent(path, node)), Match.orElse(() => void 0));
@@ -4453,7 +4660,7 @@ function nameIfAnonymous(path) {
4453
4660
  return classOrFunctionExpressionNamedIfNeeded(path) ?? arrowNameOrNode(path);
4454
4661
  }
4455
4662
  function arrowNameOrNode(path) {
4456
- return arrowFunctionExpressionNamedIfNeeded(path) ?? path.node;
4663
+ return arrowFunctionExpressionNamedIfNeeded(path) ?? expressionOf(path.node);
4457
4664
  }
4458
4665
  function isChainLink(node) {
4459
4666
  return [
@@ -4555,7 +4762,7 @@ const statementMutantPlacer = {
4555
4762
  function statementsOf(path) {
4556
4763
  const node = path.node;
4557
4764
  if (node.type === "BlockStatement") return node.body;
4558
- return [node];
4765
+ return [statementOf(node)];
4559
4766
  }
4560
4767
  function guardedStatement(statement, entry) {
4561
4768
  return ifStatement(mutantTestExpression(entry[0].id), blockStatement([nodeOfKind(entry[0], entry[1], isStatementKind, "a statement")]), statement);
@@ -4572,10 +4779,10 @@ const allMutantPlacers = Object.freeze([
4572
4779
  return nodeType(path.node) === "SwitchCase";
4573
4780
  },
4574
4781
  place(path, appliedMutants) {
4575
- const currentCase = path.node;
4782
+ const currentCase = switchCaseOf(path.node);
4576
4783
  let consequence = blockStatement([expressionStatement(mutationCoverageSequenceExpression(appliedMutants.keys())), ...currentCase.consequent]);
4577
4784
  for (const [mutant, appliedMutant] of appliedMutants) {
4578
- const appliedCase = nodeOfKind(mutant, appliedMutant, (candidate) => nodeType(candidate) === "SwitchCase", "a switch case");
4785
+ const appliedCase = nodeOfKind(mutant, appliedMutant, isSwitchCase, "a switch case");
4579
4786
  consequence = ifStatement(mutantTestExpression(mutant.id), blockStatement(appliedCase.consequent), consequence);
4580
4787
  }
4581
4788
  path.replaceWith(switchCase(currentCase.test, [consequence]));
@@ -4652,12 +4859,11 @@ const headerFor = (root) => Effect.map(instrumentationHeader, (header) => Option
4652
4859
  onSome: (leadingComments) => [commentedHeader(leadingComments, header), ...header.slice(1)]
4653
4860
  }));
4654
4861
  function leadingCommentsOf(root) {
4655
- const firstStatement = root.body[0];
4656
- return Option.filter(Option.fromNullishOr(firstStatement?.leadingComments), isCommentArray);
4862
+ return Option.filter(Option.some(leadingCommentsOn(root.body[0])), isCommentArray);
4657
4863
  }
4658
4864
  function commentedHeader(leadingComments, header) {
4659
4865
  const cloned = cloneNode(Option.getOrThrowWith(Option.fromNullishOr(header[0]), () => /* @__PURE__ */ new Error("Instrumentation header is empty")));
4660
- cloned.leadingComments = leadingComments;
4866
+ Object.assign(cloned, { leadingComments });
4661
4867
  return cloned;
4662
4868
  }
4663
4869
  function deepFreeze(value) {
@@ -5126,4 +5332,4 @@ const instrument = (files, options, basePath) => Effect.gen(function* () {
5126
5332
  });
5127
5333
  });
5128
5334
  //#endregion
5129
- export { disableTypeChecks, instrument };
5335
+ export { ERROR_CODES, INSTRUMENTER_CONSTANTS, InstrumenterOptionsSchema, LocationSchema, Mutant, MutantActivationSchema, MutantRunOptionsSchema, MutantStatusSchema, OpenEndLocationSchema, PositionSchema, RunOptionsFields, causeText, disableTypeChecks, errorToString, instrument, isErrnoException, isMutant, normalizeFileName };