@systemfsoftware/stryker-js-instrumenter 7.1.0 → 8.0.1

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