@gi-tcg/gts-transpiler 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,7 +3,8 @@ import { tsPlugin } from "@sveltejs/acorn-typescript";
3
3
  import { walk } from "zimmerframe";
4
4
  import { print } from "esrap";
5
5
  import jsPrinter from "esrap/languages/ts";
6
- import { decode } from "@jridgewell/sourcemap-codec";
6
+ import { defaultPrinters, print as print$1 } from "espolar";
7
+ import dedent from "dedent";
7
8
  import path from "path-browserify-esm";
8
9
  //#region src/keywords.ts
9
10
  const specialIdentifiers = [
@@ -77,7 +78,7 @@ function loosePlugin() {
77
78
  return value;
78
79
  } });
79
80
  createDummyIdentifier() {
80
- const dummy = this.startNode();
81
+ const dummy = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
81
82
  dummy.name = "✖";
82
83
  dummy.isDummy = true;
83
84
  return this.finishNode(dummy, "Identifier");
@@ -197,7 +198,7 @@ function gtsPlugin(options = {}) {
197
198
  return this.gts_parseShortcutFunction();
198
199
  }
199
200
  if (this.gtsOptions.allowEmptyPositionalAttribute && (this.type === tokTypes.comma || this.type === tokTypes.braceR || this.type === tokTypes.semi || this.canInsertSemicolon() || this.isContextual("as"))) {
200
- const dummy = this.startNode();
201
+ const dummy = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
201
202
  dummy.name = "✖";
202
203
  dummy.isDummy = true;
203
204
  return this.finishNode(dummy, "Identifier");
@@ -228,7 +229,7 @@ function gtsPlugin(options = {}) {
228
229
  const node = this.startNode();
229
230
  this.next();
230
231
  if (this.gtsOptions.allowEmptyShortcutMember && this.type !== tokTypes.name) {
231
- const dummy = this.startNode();
232
+ const dummy = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
232
233
  dummy.name = "✖";
233
234
  dummy.isDummy = true;
234
235
  node.property = this.finishNode(dummy, "Identifier");
@@ -475,35 +476,29 @@ var GtsTranspilerError = class extends Error {
475
476
  //#endregion
476
477
  //#region src/parse/record_call_lparen_plugin.ts
477
478
  /**
478
- * A plugin that records the location of the left parenthesis in CallExpression and
479
+ * A plugin that records the location of the left parenthesis in CallExpression and
479
480
  * NewExpression.
480
- *
481
- * This is useful for Language tooling, that we can maps the '(' token from its location,
482
- * to provide * a signature help for user when they press `(` after a function name.
483
481
  *
484
- * The recorded location will be stored in `lParenLoc` property of the
482
+ * This is useful for Language tooling, that we can maps the '(' token from its location,
483
+ * to provide a signature help for user when they press `(` after a function name.
484
+ *
485
+ * The recorded location will be stored in `lParenLoc` property of the
485
486
  * CallExpression/NewExpression node.
486
- * @returns
487
+ * @returns the plugin function
487
488
  */
488
489
  function recordCallLParenPlugin() {
489
490
  return function recordCallLParenPluginTransformer(parser) {
490
491
  return class RecordCallLParenParser extends parser {
491
492
  parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
492
493
  let recordedLParenLoc = null;
493
- if (!noCalls && this.type === tokTypes.parenL) recordedLParenLoc = {
494
- start: this.startLoc,
495
- end: this.endLoc
496
- };
494
+ if (!noCalls && this.type === tokTypes.parenL) recordedLParenLoc = [this.start, this.end];
497
495
  const result = super.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
498
- if (recordedLParenLoc && result.type === "CallExpression") result.lParenLoc = recordedLParenLoc;
496
+ if (recordedLParenLoc && result.type === "CallExpression") result.lParenRange = recordedLParenLoc;
499
497
  return result;
500
498
  }
501
- _capturedLParenLocFromNew = null;
499
+ _capturedLParenRangeFromNew = null;
502
500
  _patchedEat = (type) => {
503
- if (type === tokTypes.parenL) this._capturedLParenLocFromNew = {
504
- start: this.startLoc,
505
- end: this.endLoc
506
- };
501
+ if (type === tokTypes.parenL) this._capturedLParenRangeFromNew = [this.start, this.end];
507
502
  return this.eat(type);
508
503
  };
509
504
  #proxiedThis = new Proxy(this, { get: (target, prop) => {
@@ -514,9 +509,9 @@ function recordCallLParenPlugin() {
514
509
  } });
515
510
  parseNew() {
516
511
  const result = super.parseNew.apply(this.#proxiedThis);
517
- if (this._capturedLParenLocFromNew && result.type === "NewExpression") {
518
- result.lParenLoc = this._capturedLParenLocFromNew;
519
- this._capturedLParenLocFromNew = null;
512
+ if (this._capturedLParenRangeFromNew && result.type === "NewExpression") {
513
+ result.lParenRange = this._capturedLParenRangeFromNew;
514
+ this._capturedLParenRangeFromNew = null;
520
515
  }
521
516
  return result;
522
517
  }
@@ -531,7 +526,8 @@ function parse(input, options) {
531
526
  return TsParser.extend(gtsPlugin(options)).parse(input, {
532
527
  ecmaVersion: "latest",
533
528
  sourceType: "module",
534
- locations: true
529
+ locations: true,
530
+ ranges: true
535
531
  });
536
532
  } catch (e) {
537
533
  if (e instanceof SyntaxError && "loc" in e) {
@@ -557,6 +553,7 @@ function parseLoose(input, options) {
557
553
  ecmaVersion: "latest",
558
554
  sourceType: "module",
559
555
  locations: true,
556
+ ranges: true,
560
557
  onComment
561
558
  });
562
559
  addComments(ast);
@@ -744,7 +741,8 @@ const commonGtsVisitor = {
744
741
  method: false,
745
742
  shorthand: false,
746
743
  value: state.ActionLit,
747
- loc: node.loc
744
+ loc: node.loc,
745
+ range: node.range
748
746
  },
749
747
  {
750
748
  type: "Property",
@@ -790,7 +788,8 @@ const commonGtsVisitor = {
790
788
  }
791
789
  }
792
790
  ],
793
- loc: node.loc
791
+ loc: node.loc,
792
+ range: node.range
794
793
  };
795
794
  },
796
795
  GTSShortcutFunctionExpression(node, { visit, state }) {
@@ -799,7 +798,8 @@ const commonGtsVisitor = {
799
798
  params: state.shortcutFunctionParameters,
800
799
  body: visit(node.body),
801
800
  expression: node.expression,
802
- loc: node.loc
801
+ loc: node.loc,
802
+ range: node.range
803
803
  };
804
804
  },
805
805
  GTSShortcutArgumentExpression(node, { state, visit }) {
@@ -809,7 +809,8 @@ const commonGtsVisitor = {
809
809
  computed: false,
810
810
  optional: false,
811
811
  property: visit(node.property),
812
- loc: node.loc
812
+ loc: node.loc,
813
+ range: node.range
813
814
  };
814
815
  },
815
816
  GTSQueryExpression(node, { state, visit }) {
@@ -824,7 +825,8 @@ const commonGtsVisitor = {
824
825
  body: visit(node.argument),
825
826
  params: state.queryParameters,
826
827
  expression: true,
827
- loc: node.argument.loc
828
+ loc: node.argument.loc,
829
+ range: node.argument.range
828
830
  }, {
829
831
  type: "ObjectExpression",
830
832
  properties: [{
@@ -938,7 +940,8 @@ const gtsVisitor = {
938
940
  id: nodeVarId,
939
941
  init: rootAttr
940
942
  }],
941
- loc: node.loc
943
+ loc: node.loc,
944
+ range: node.range
942
945
  });
943
946
  state.bindingStatements.push({
944
947
  type: "VariableDeclaration",
@@ -953,7 +956,8 @@ const gtsVisitor = {
953
956
  arguments: [state.rootVmId, nodeVarId]
954
957
  }
955
958
  }],
956
- loc: node.loc
959
+ loc: node.loc,
960
+ range: node.range
957
961
  });
958
962
  for (let i = 0; i < newBindings.length; i++) {
959
963
  const binding = newBindings[i];
@@ -991,7 +995,8 @@ const gtsVisitor = {
991
995
  callee: state.createDefineFnId,
992
996
  arguments: [state.rootVmId, nodeVarId]
993
997
  },
994
- loc: node.loc
998
+ loc: node.loc,
999
+ range: node.range
995
1000
  };
996
1001
  },
997
1002
  GTSNamedAttributeDefinition(node, { visit, state }) {
@@ -1013,7 +1018,8 @@ const gtsVisitor = {
1013
1018
  method: false,
1014
1019
  shorthand: false,
1015
1020
  value: nameValue,
1016
- loc: node.loc
1021
+ loc: node.loc,
1022
+ range: node.range
1017
1023
  });
1018
1024
  const body = {
1019
1025
  ...namedBody,
@@ -1067,9 +1073,11 @@ const gtsVisitor = {
1067
1073
  params: [],
1068
1074
  body: positionals,
1069
1075
  expression: true,
1070
- loc: positionals.loc
1076
+ loc: positionals.loc,
1077
+ range: positionals.range
1071
1078
  },
1072
- loc: positionals.loc
1079
+ loc: positionals.loc,
1080
+ range: positionals.range
1073
1081
  }, {
1074
1082
  type: "Property",
1075
1083
  key: {
@@ -1081,9 +1089,11 @@ const gtsVisitor = {
1081
1089
  method: false,
1082
1090
  shorthand: false,
1083
1091
  value: named,
1084
- loc: named.loc
1092
+ loc: named.loc,
1093
+ range: named.range
1085
1094
  }],
1086
- loc: node.loc
1095
+ loc: node.loc,
1096
+ range: node.range
1087
1097
  };
1088
1098
  },
1089
1099
  GTSPositionalAttributeList(node, { visit }) {
@@ -1097,7 +1107,8 @@ const gtsVisitor = {
1097
1107
  };
1098
1108
  else return visit(attr);
1099
1109
  }),
1100
- loc: node.loc
1110
+ loc: node.loc,
1111
+ range: node.range
1101
1112
  };
1102
1113
  },
1103
1114
  GTSNamedAttributeBlock(node, { visit }) {
@@ -1120,7 +1131,8 @@ const gtsVisitor = {
1120
1131
  elements: attributes
1121
1132
  }
1122
1133
  }],
1123
- loc: node.loc
1134
+ loc: node.loc,
1135
+ range: node.range
1124
1136
  };
1125
1137
  },
1126
1138
  ...commonGtsVisitor
@@ -1255,25 +1267,26 @@ const createReplacementHolder = (state, value) => {
1255
1267
  }
1256
1268
  };
1257
1269
  };
1258
- function applyReplacements(state, code) {
1259
- const replacementRegex = new RegExp("\\b" + state.replacementTag.name + "`(.*?)`", "gm");
1270
+ function applyReplacements(state, code, mappings) {
1271
+ const replacementRegex = new RegExp("\\b" + state.replacementTag.name + "`(.*?)(?<!\\\\)`", "gm");
1260
1272
  const { NamedDefinitionLit, MetaLit } = state;
1261
1273
  const NamedDefinition = JSON.stringify(NamedDefinitionLit.value);
1262
1274
  const Meta = JSON.stringify(MetaLit.value);
1263
- const oneLine = (strings, ...values) => strings.reduce((result, chunk, index) => result + chunk + (index < values.length ? values[index] : ""), "").replace(/\n[ \t]*/g, " ").trim();
1264
- return code.replace(replacementRegex, (_, rawPayload) => {
1265
- const payload = JSON.parse(rawPayload);
1266
- if (payload.type === "preface") return oneLine`
1275
+ const matchInfos = [];
1276
+ const result = code.replace(replacementRegex, (match, rawPayload, offset) => {
1277
+ const payload = JSON.parse(rawPayload.replace(/\\`/g, "`"));
1278
+ let replacement;
1279
+ if (payload.type === "preface") replacement = dedent`
1267
1280
  namespace ${state.utilNsId.name} {
1268
1281
  export type UniqueKeyProbSegment = "__gts_unique_prob_seg__";
1269
1282
  export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
1270
1283
  }
1271
1284
  `;
1272
- else if (payload.type === "enterVMFromRoot") return oneLine`
1285
+ else if (payload.type === "enterVMFromRoot") replacement = dedent`
1273
1286
  type ${payload.defType} = (typeof ${payload.vm})[${NamedDefinition}];
1274
1287
  type ${payload.metaType} = ${payload.defType}[${Meta}];
1275
1288
  `;
1276
- else if (payload.type === "enterVMFromAttr") return oneLine`
1289
+ else if (payload.type === "enterVMFromAttr") replacement = dedent`
1277
1290
  type ${payload.defType} = ${payload.returnType} extends { namedDefinition: infer Def } ? Def : { ${Meta}: unknown };
1278
1291
  type ${payload.metaType} = ${payload.defType}[${Meta}];
1279
1292
  `;
@@ -1282,8 +1295,12 @@ function applyReplacements(state, code) {
1282
1295
  const requiredAttrsNs = `${payload.finalMetaType}_rans`;
1283
1296
  const collectedAttrsExpr = `${payload.collectedAttrs.join(" | ")}`;
1284
1297
  const needleString = `"${requiredAttrsNs}_NeedleString" as any as "required attributes are missing"`;
1285
- if (payload.errorLoc) state.extraMappings.set(payload.errorLoc, needleString);
1286
- return oneLine`
1298
+ if (payload.errorRange) state.extraMappings.push({
1299
+ sourceOffset: payload.errorRange[0],
1300
+ length: payload.errorRange[1] - payload.errorRange[0],
1301
+ generatedNeedle: needleString
1302
+ });
1303
+ replacement = dedent`
1287
1304
  type ${payload.finalMetaType} = ${payload.metaType};
1288
1305
  let ${lhs}!: { ${Meta}: ${payload.metaType} } & Omit<${payload.defType}, ${Meta}>;
1289
1306
  type ${lhs} = typeof ${lhs};
@@ -1299,10 +1316,11 @@ function applyReplacements(state, code) {
1299
1316
  const uniqueKeyForThis = `${payload.lhs}_uniqueKeyFor_${payload.lhs}`;
1300
1317
  const uniqueKeyHelperIntf = `${payload.defType}_uniqueKeyProbeHelper`;
1301
1318
  const omittedKeys = `${payload.lhs}_omittedKeys`;
1302
- return oneLine`
1319
+ replacement = dedent`
1303
1320
  type ${uniqueKeyLhs} = {
1304
1321
  ${Meta}: ${payload.metaType};
1305
1322
  uniqueKey: ${payload.defType} extends { [${payload.attrName}]: { uniqueKey: infer UniqueKey } } ? UniqueKey : () => 0;
1323
+ };
1306
1324
 
1307
1325
  let ${uniqueKeyLhs}!: ${uniqueKeyLhs};
1308
1326
  let ${uniqueKey} = ${uniqueKeyLhs}.uniqueKey();
@@ -1326,7 +1344,7 @@ function applyReplacements(state, code) {
1326
1344
  `;
1327
1345
  } else if (payload.type === "createBindingTyping") {
1328
1346
  const typingIdLhs = `${payload.typingId}_lhs`;
1329
- return oneLine`
1347
+ replacement = dedent`
1330
1348
  type ${typingIdLhs} = {
1331
1349
  ${Meta}: ${payload.finalMetaType};
1332
1350
  as: ${payload.defType} extends { [${payload.attrName}]: { as: infer As } } ? As : unknown;
@@ -1335,12 +1353,24 @@ function applyReplacements(state, code) {
1335
1353
  let ${payload.typingId} = ${typingIdLhs}.as();
1336
1354
  type ${payload.typingId} = typeof ${payload.typingId};
1337
1355
  `;
1338
- } else if (payload.type === "exitAttr") return oneLine`
1356
+ } else if (payload.type === "exitAttr") replacement = dedent`
1339
1357
  type ${payload.returnType} = typeof ${payload.returnType};
1340
1358
  type ${payload.newMetaType} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType}
1341
1359
  `;
1342
- else return "";
1360
+ else replacement = "";
1361
+ matchInfos.push({
1362
+ sourceEnd: offset + match.length,
1363
+ lengthOffset: replacement.length - match.length
1364
+ });
1365
+ return replacement;
1343
1366
  });
1367
+ for (const mapping of mappings) for (let i = 0; i < mapping.generatedOffsets.length; i++) {
1368
+ const orig = mapping.generatedOffsets[i];
1369
+ let shift = 0;
1370
+ for (const info of matchInfos) if (orig >= info.sourceEnd) shift += info.lengthOffset;
1371
+ mapping.generatedOffsets[i] = orig + shift;
1372
+ }
1373
+ return result;
1344
1374
  }
1345
1375
  //#endregion
1346
1376
  //#region src/transform/volar/walker.ts
@@ -1401,7 +1431,7 @@ const enterVMFromAttr = (state, returningId) => {
1401
1431
  state.finalMetaTypeIdStack.push(finalMetaTypeId);
1402
1432
  state.attrsOfCurrentVm.push([]);
1403
1433
  };
1404
- const exitVM = (state, errorLoc) => {
1434
+ const exitVM = (state, errorRange) => {
1405
1435
  const currentDefTypeId = state.vmDefTypeIdStack.pop();
1406
1436
  const currentMetaId = state.metaTypeIdStack.pop();
1407
1437
  const finalMetaId = state.finalMetaTypeIdStack.pop();
@@ -1412,7 +1442,7 @@ const exitVM = (state, errorLoc) => {
1412
1442
  defType: currentDefTypeId.name,
1413
1443
  finalMetaType: finalMetaId.name,
1414
1444
  collectedAttrs: collectedAttrNames,
1415
- errorLoc
1445
+ errorRange
1416
1446
  }));
1417
1447
  };
1418
1448
  const enterAttr = (state, attrName) => {
@@ -1420,7 +1450,7 @@ const enterAttr = (state, attrName) => {
1420
1450
  const metaTypeId = state.metaTypeIdStack.at(-1);
1421
1451
  if (!defTypeId || !metaTypeId) return { lhsId: {
1422
1452
  type: "Identifier",
1423
- name: "__invalid_attr_obj"
1453
+ name: "__gts_invalid_attr_obj"
1424
1454
  } };
1425
1455
  state.attrsOfCurrentVm.at(-1).push(attrName);
1426
1456
  const lhsId = {
@@ -1503,9 +1533,9 @@ const gtsToTypingsWalker = {
1503
1533
  body.unshift(varDecl);
1504
1534
  }
1505
1535
  }
1506
- if (state.hasQueryExpressions) body.unshift({
1536
+ const importDecls = [];
1537
+ if (state.hasQueryExpressions) importDecls.push({
1507
1538
  type: "ImportDeclaration",
1508
- diagnosticsOnTop: true,
1509
1539
  specifiers: [{
1510
1540
  type: "ImportDefaultSpecifier",
1511
1541
  local: state.queryFnId
@@ -1516,9 +1546,8 @@ const gtsToTypingsWalker = {
1516
1546
  },
1517
1547
  attributes: []
1518
1548
  });
1519
- body.unshift({
1549
+ importDecls.push({
1520
1550
  type: "ImportDeclaration",
1521
- diagnosticsOnTop: true,
1522
1551
  specifiers: [{
1523
1552
  type: "ImportDefaultSpecifier",
1524
1553
  local: state.rootVmId
@@ -1528,7 +1557,12 @@ const gtsToTypingsWalker = {
1528
1557
  value: `${state.providerImportSource}/vm`
1529
1558
  },
1530
1559
  attributes: []
1531
- }, createReplacementHolder(state, { type: "preface" }));
1560
+ });
1561
+ for (const importDecl of importDecls) {
1562
+ state.diagnosticsOnTopNodes.add(importDecl.source);
1563
+ for (const specifier of importDecl.specifiers) state.diagnosticsOnTopNodes.add(specifier);
1564
+ }
1565
+ body.unshift(...importDecls, createReplacementHolder(state, { type: "preface" }));
1532
1566
  return {
1533
1567
  ...node,
1534
1568
  body
@@ -1543,28 +1577,41 @@ const gtsToTypingsWalker = {
1543
1577
  GTSNamedAttributeDefinition(node, { visit, state }) {
1544
1578
  const { name, body, bindingName } = node;
1545
1579
  const attrName = JSON.stringify(name.type === "Literal" ? String(name.value) : name.name);
1546
- const attributeNameToken = state.leafTokens.find((t) => t.loc === name.loc);
1547
- if (attributeNameToken) attributeNameToken.sourceLengthOffset = 1;
1548
1580
  const { lhsId } = enterAttr(state, attrName);
1549
- state.extraMappings.set(`${name.loc?.start.line}:${name.loc?.start.column}`, `${lhsId.name}${name.type === "Literal" ? `[` : `.`}`);
1550
1581
  const positionals = body.positionalAttributes.attributes.map((attr) => {
1551
1582
  if (attr.type === "Identifier" && /^[a-z_]/.test(attr.name)) {
1552
- const token = state.leafTokens.find((t) => t.loc === attr.loc);
1553
- if (token) {
1554
- token.generatedStartOffset = 1;
1555
- token.generatedLength = attr.name.length + 2;
1556
- }
1557
- return {
1583
+ const lit = {
1558
1584
  type: "Literal",
1559
1585
  value: attr.name,
1560
- loc: attr.loc
1586
+ loc: attr.loc,
1587
+ range: attr.range
1561
1588
  };
1562
- } else return visit(attr);
1589
+ state.literalFromIdentifier.add(lit);
1590
+ return lit;
1591
+ } else return { ...visit(attr) };
1563
1592
  });
1564
1593
  const returnValue = {
1565
1594
  type: "Identifier",
1566
1595
  name: `__gts_attrRet_${state.idCounter++}`
1567
1596
  };
1597
+ const callee = {
1598
+ type: "MemberExpression",
1599
+ object: lhsId,
1600
+ property: name,
1601
+ computed: name.type === "Literal",
1602
+ optional: false
1603
+ };
1604
+ if (name.range) {
1605
+ state.extraMappings.push({
1606
+ sourceOffset: name.range[0],
1607
+ length: name.range[1] - name.range[0],
1608
+ generatedNeedle: `${lhsId.name}${name.type === "Literal" ? `[` : `.`}`
1609
+ });
1610
+ state.namedAttributeCalleeLParenRange.set(callee, {
1611
+ start: name.range[1],
1612
+ end: name.range[1] + 1
1613
+ });
1614
+ }
1568
1615
  state.typingPendingStatements.push({
1569
1616
  type: "VariableDeclaration",
1570
1617
  kind: "const",
@@ -1574,13 +1621,7 @@ const gtsToTypingsWalker = {
1574
1621
  init: {
1575
1622
  type: "CallExpression",
1576
1623
  optional: false,
1577
- callee: {
1578
- type: "MemberExpression",
1579
- object: lhsId,
1580
- property: name,
1581
- computed: name.type === "Literal",
1582
- optional: false
1583
- },
1624
+ callee,
1584
1625
  arguments: positionals
1585
1626
  }
1586
1627
  }]
@@ -1588,13 +1629,13 @@ const gtsToTypingsWalker = {
1588
1629
  if (body.namedAttributes) {
1589
1630
  enterVMFromAttr(state, returnValue);
1590
1631
  visit(body.namedAttributes);
1591
- exitVM(state, `${body.namedAttributes.loc?.start.line}:${body.namedAttributes.loc?.start.column}`);
1632
+ exitVM(state, body.namedAttributes.range);
1592
1633
  }
1593
1634
  if (bindingName) {
1594
1635
  const export_ = node.bindingAccessModifier !== "private";
1595
1636
  const typingId = {
1596
1637
  type: "Identifier",
1597
- name: `gts_binding_type_${state.externalizedBindings.length}`
1638
+ name: `__gts_binding_type_${state.externalizedBindings.length}`
1598
1639
  };
1599
1640
  genBindingTyping(state, {
1600
1641
  attrName,
@@ -1625,8 +1666,11 @@ const gtsToTypingsWalker = {
1625
1666
  const attrName = JSON.stringify(state.ActionLit.value);
1626
1667
  const { lhsId } = enterAttr(state, attrName);
1627
1668
  const actionNotExistsReplacementStr = `${lhsId.name}[${attrName}]`;
1628
- const actionNotExistsErrorLoc = `${node.directAction.loc?.start.line}:${node.directAction.loc?.start.column}`;
1629
- state.extraMappings.set(actionNotExistsErrorLoc, actionNotExistsReplacementStr);
1669
+ if (node.directAction.range) state.extraMappings.push({
1670
+ sourceOffset: node.directAction.range[0],
1671
+ length: node.directAction.range[1] - node.directAction.range[0],
1672
+ generatedNeedle: actionNotExistsReplacementStr
1673
+ });
1630
1674
  const fn = {
1631
1675
  type: "ArrowFunctionExpression",
1632
1676
  params: state.shortcutFunctionParameters,
@@ -1663,16 +1707,7 @@ const gtsToTypingsWalker = {
1663
1707
  }
1664
1708
  return EMPTY;
1665
1709
  },
1666
- ...commonGtsVisitor,
1667
- GTSShortcutArgumentExpression(node, { state, visit }) {
1668
- return {
1669
- type: "MemberExpression",
1670
- object: { ...state.fnArgId },
1671
- computed: false,
1672
- optional: false,
1673
- property: visit(node.property)
1674
- };
1675
- }
1710
+ ...commonGtsVisitor
1676
1711
  };
1677
1712
  //#endregion
1678
1713
  //#region src/transform/volar/mappings.ts
@@ -1684,291 +1719,74 @@ const DEFAULT_VOLAR_MAPPING_DATA = {
1684
1719
  structure: true,
1685
1720
  verification: true
1686
1721
  };
1687
- /**
1688
- * Build a source-to-generated position lookup map from an esrap source map
1689
- * Applies post-processing adjustments during map building for efficiency
1690
- * @param source_map - The source map object from esrap (v3 format)
1691
- * @param line_offsets - Pre-computed line offsets array
1692
- * @param generated_code - The final generated code (after post-processing)
1693
- * @returns source-to-generated map
1694
- */
1695
- function buildSrcToGenMap(source_map, line_offsets, generated_code) {
1696
- const map = /* @__PURE__ */ new Map();
1697
- const decoded = decode(source_map.mappings);
1698
- /**
1699
- * Convert line/column position to byte offset
1700
- * @param {number} line - 1-based line number
1701
- * @param {number} column - 0-based column number
1702
- * @returns {number} Byte offset
1703
- */
1704
- const line_col_to_byte_offset = (line, column) => {
1705
- return line_offsets[line - 1] + column;
1706
- };
1707
- const adjusted_segments = [];
1708
- for (let generated_line = 0; generated_line < decoded.length; generated_line++) {
1709
- const line = decoded[generated_line];
1710
- adjusted_segments[generated_line] = [];
1711
- for (const segment of line) if (segment.length >= 4) {
1712
- let adjusted_line = generated_line + 1;
1713
- let adjusted_column = segment[0];
1714
- adjusted_segments[generated_line].push({
1715
- line: adjusted_line,
1716
- column: adjusted_column,
1717
- sourceLine: segment[2],
1718
- sourceColumn: segment[3]
1719
- });
1720
- }
1721
- }
1722
- for (let line_idx = 0; line_idx < adjusted_segments.length; line_idx++) {
1723
- const line_segments = adjusted_segments[line_idx];
1724
- for (let seg_idx = 0; seg_idx < line_segments.length; seg_idx++) {
1725
- const segment = line_segments[seg_idx];
1726
- const line = segment.line;
1727
- const column = segment.column;
1728
- let end_line = line;
1729
- let end_column = column;
1730
- if (seg_idx + 1 < line_segments.length) {
1731
- const next_segment = line_segments[seg_idx + 1];
1732
- end_line = next_segment.line;
1733
- end_column = next_segment.column;
1734
- } else if (line_idx + 1 < adjusted_segments.length && adjusted_segments[line_idx + 1].length > 0) {
1735
- const next_segment = adjusted_segments[line_idx + 1][0];
1736
- end_line = next_segment.line;
1737
- end_column = next_segment.column;
1738
- }
1739
- const start_offset = line_col_to_byte_offset(line, column);
1740
- const end_offset = line_col_to_byte_offset(end_line, end_column);
1741
- const code_snippet = generated_code.slice(start_offset, end_offset);
1742
- segment.sourceLine += 1;
1743
- const key = `${segment.sourceLine}:${segment.sourceColumn}`;
1744
- const gen_pos = {
1745
- line,
1746
- column,
1747
- end_line,
1748
- end_column,
1749
- code: code_snippet,
1750
- metadata: {}
1751
- };
1752
- if (!map.has(key)) map.set(key, []);
1753
- map.get(key).push(gen_pos);
1754
- }
1755
- }
1756
- return map;
1757
- }
1758
- /**
1759
- * Look up generated position for a given source position
1760
- * @param src_line - 1-based line number in source
1761
- * @param src_column - 0-based column number in source
1762
- * @param srcToGenMap - Lookup map
1763
- * @returns Generated position
1764
- */
1765
- function getGeneratedPosition(src_line, src_column, srcToGenMap) {
1766
- const key = `${src_line}:${src_column}`;
1767
- return srcToGenMap.get(key) || [];
1768
- }
1769
- function createLineOffsets(content) {
1770
- const lines = content.split("\n");
1771
- const offsets = [];
1772
- let currentOffset = 0;
1773
- for (const line of lines) {
1774
- offsets.push(currentOffset);
1775
- currentOffset += line.length + 1;
1776
- }
1777
- return offsets;
1778
- }
1779
- /**
1780
- * Convert line/column to byte offset
1781
- * @param line
1782
- * @param column
1783
- * @param line_offsets
1784
- * @returns
1785
- */
1786
- function locToOffset(line, column, line_offsets) {
1787
- if (line < 1 || line > line_offsets.length) {}
1788
- return line_offsets[line - 1] + column;
1789
- }
1790
- function convertToVolarMappings(generated, source, sourceMap, tokens, extraMappings) {
1791
- const sourceLineOffsets = createLineOffsets(source);
1792
- const generatedLineOffsets = createLineOffsets(generated);
1793
- const srcToGenMap = buildSrcToGenMap(sourceMap, generatedLineOffsets, generated);
1794
- const mappings = [];
1795
- for (const token of tokens) {
1796
- let sourceStart = locToOffset(token.loc.start.line, token.loc.start.column, sourceLineOffsets);
1797
- sourceStart += token.sourceStartOffset ?? 0;
1798
- const sourceEnd = locToOffset(token.loc.end.line, token.loc.end.column, sourceLineOffsets);
1799
- let sourceLength = token.sourceLength ?? sourceEnd - sourceStart;
1800
- sourceLength += token.sourceLengthOffset ?? 0;
1801
- const [genLineCol] = getGeneratedPosition(token.loc.start.line, token.loc.start.column, srcToGenMap);
1802
- if (!genLineCol) continue;
1803
- let genStart = locToOffset(genLineCol.line, genLineCol.column, generatedLineOffsets);
1804
- if (token.isDummy) while (sourceStart > 0 && /\s/.test(source[sourceStart - 1])) {
1805
- sourceStart--;
1806
- sourceLength++;
1807
- }
1808
- const generatedLength = token.generatedLength ?? sourceLength;
1809
- if (typeof token.generatedStartOffset === "number" && token.generatedStartOffset > 0) {
1810
- mappings.push({
1811
- sourceOffsets: [sourceStart],
1812
- generatedOffsets: [genStart],
1813
- lengths: [0],
1814
- generatedLengths: [generatedLength],
1815
- data: { verification: true }
1816
- });
1817
- genStart += token.generatedStartOffset;
1818
- }
1819
- mappings.push({
1820
- sourceOffsets: [sourceStart],
1821
- generatedOffsets: [genStart],
1822
- lengths: [sourceLength],
1823
- generatedLengths: [generatedLength],
1824
- data: DEFAULT_VOLAR_MAPPING_DATA
1825
- });
1826
- }
1827
- const locMapsToTop = getGeneratedPosition(1, 0, srcToGenMap);
1828
- for (const loc of locMapsToTop) {
1829
- const offset = locToOffset(loc.line, loc.column, generatedLineOffsets);
1830
- mappings.push({
1831
- sourceOffsets: [0],
1832
- generatedOffsets: [offset],
1833
- lengths: [0],
1834
- generatedLengths: [0],
1835
- data: { verification: true }
1836
- });
1837
- }
1838
- for (const [loc, codeSnippet] of extraMappings) {
1839
- const generatedStart = generated.indexOf(codeSnippet);
1840
- if (generatedStart === -1) continue;
1841
- const [lineStr, columnStr] = loc.split(":");
1842
- const sourceStart = locToOffset(Number(lineStr), Number(columnStr), sourceLineOffsets);
1843
- const sourceLength = 1;
1844
- const generatedLength = codeSnippet.length;
1845
- mappings.push({
1846
- sourceOffsets: [sourceStart],
1847
- generatedOffsets: [generatedStart],
1848
- lengths: [sourceLength],
1849
- generatedLengths: [generatedLength],
1850
- data: { verification: true }
1851
- });
1852
- }
1853
- mappings.sort((a, b) => a.sourceOffsets[0] - b.sourceOffsets[0]);
1854
- return mappings;
1855
- }
1722
+ const VERIFICATION_ONLY_MAPPING_DATA = { verification: true };
1723
+ Object.freeze(DEFAULT_VOLAR_MAPPING_DATA);
1724
+ Object.freeze(VERIFICATION_ONLY_MAPPING_DATA);
1856
1725
  //#endregion
1857
- //#region src/transform/volar/collect_tokens.ts
1858
- function isLeafNode(node) {
1859
- for (const key in node) {
1860
- const val = node[key];
1861
- if (key === "loc" || key === "start" || key === "end" || key === "range") continue;
1862
- if (val && typeof val === "object" && typeof val.type === "string") return false;
1863
- if (Array.isArray(val) && val.length > 0 && typeof val[0].type === "string") return false;
1864
- }
1865
- return true;
1866
- }
1867
- function collectLeafTokens(ast) {
1868
- const state = { tokens: [] };
1869
- walk(ast, state, {
1870
- _(node, { state, next }) {
1871
- if (isLeafNode(node) && node.loc) {
1872
- const token = { loc: node.loc };
1873
- if ("isDummy" in node && node.isDummy) {
1874
- token.isDummy = true;
1875
- token.sourceLength = 0;
1876
- token.generatedLength = 1;
1726
+ //#region src/transform/volar/printer.ts
1727
+ function getPrintOptions(source, state) {
1728
+ return {
1729
+ source,
1730
+ isUntouched: (node) => {
1731
+ if (node.type === "Identifier" && node.isDummy) return false;
1732
+ return state.sourceNodes.has(node);
1733
+ },
1734
+ getLeadingComments: (node) => node.leadingComments,
1735
+ getTrailingComments: (node) => node.trailingComments,
1736
+ getMappingData: () => DEFAULT_VOLAR_MAPPING_DATA,
1737
+ printers: {
1738
+ Identifier(node, context) {
1739
+ const identifier = node;
1740
+ if (identifier.isDummy && identifier.range) {
1741
+ const text = state.lastArgNodes.has(identifier) ? "," : "";
1742
+ let firstNonWhiteSpaceIndex = context.source.slice(identifier.range[1]).search(/\S/);
1743
+ const rangeEnd = firstNonWhiteSpaceIndex === -1 ? context.source.length : identifier.range[1] + firstNonWhiteSpaceIndex;
1744
+ context.writeMapped(text, identifier.range[0], rangeEnd);
1745
+ } else return defaultPrinters.Identifier(node, context);
1746
+ },
1747
+ Literal(node, context) {
1748
+ const generatedStart = context.generatedOffset;
1749
+ if (state.literalFromIdentifier.has(node) && node.range) {
1750
+ const text = JSON.stringify(node.value);
1751
+ context.write("\"");
1752
+ context.writeMapped(text.slice(1, -1), node.range[0], node.range[1]);
1753
+ context.write("\"");
1754
+ } else defaultPrinters.Literal(node, context);
1755
+ if (state.diagnosticsOnTopNodes.has(node)) {
1756
+ const generatedEnd = context.generatedOffset;
1757
+ context.createExtraMapping({
1758
+ start: 0,
1759
+ end: 1
1760
+ }, generatedStart, generatedEnd, VERIFICATION_ONLY_MAPPING_DATA);
1761
+ }
1762
+ },
1763
+ ImportDefaultSpecifier(node, context) {
1764
+ const generatedStart = context.generatedOffset;
1765
+ defaultPrinters.ImportDefaultSpecifier(node, context);
1766
+ if (state.diagnosticsOnTopNodes.has(node)) {
1767
+ const generatedEnd = context.generatedOffset;
1768
+ context.createExtraMapping({
1769
+ start: 0,
1770
+ end: 1
1771
+ }, generatedStart, generatedEnd, VERIFICATION_ONLY_MAPPING_DATA);
1877
1772
  }
1878
- state.tokens.push(token);
1879
1773
  }
1880
- next();
1881
1774
  },
1882
- NewExpression(node, { state, next }) {
1883
- const lParenLoc = node.lParenLoc;
1884
- if (lParenLoc) state.tokens.push({ loc: lParenLoc });
1885
- next();
1886
- },
1887
- CallExpression(node, { state, next }) {
1888
- const lParenLoc = node.lParenLoc;
1889
- if (lParenLoc) state.tokens.push({ loc: lParenLoc });
1890
- next();
1891
- }
1892
- });
1893
- return state.tokens;
1894
- }
1895
- //#endregion
1896
- //#region src/transform/volar/printer.ts
1897
- const printer = jsPrinter({
1898
- getLeadingComments: (node) => node.leadingComments,
1899
- getTrailingComments: (node) => node.trailingComments
1900
- });
1901
- const prevIdentifier = printer.Identifier;
1902
- printer.Identifier = function(node, context) {
1903
- if (node.isDummy) {
1904
- const text = Reflect.get(node, "lastArg") ? "," : "";
1905
- context.write(text, node);
1906
- } else prevIdentifier(node, context);
1907
- };
1908
- const prevCallNewExpression = printer.CallExpression;
1909
- const newCallNewExpression = function(node, context) {
1910
- const lastArg = node.arguments.at(-1);
1911
- if (lastArg) Reflect.set(lastArg, "lastArg", true);
1912
- if (!node.lParenLoc) return prevCallNewExpression(node, context);
1913
- let hasDeferredWrite = false;
1914
- let interceptionDone = false;
1915
- const lParenFakeNode = { loc: node.lParenLoc };
1916
- const patchedWrite = (text, node) => {
1917
- if (text === "(") hasDeferredWrite = true;
1918
- else context.write(text, node);
1919
- };
1920
- const patchedVisit = (node) => {
1921
- if (hasDeferredWrite) context.write("(");
1922
- return context.visit(node);
1923
- };
1924
- const patchedAppend = (subcontext) => {
1925
- if (hasDeferredWrite) {
1926
- context.write("(", lParenFakeNode);
1927
- interceptionDone = true;
1928
- }
1929
- return context.append(subcontext);
1930
- };
1931
- return prevCallNewExpression(node, new Proxy(context, { get(target, prop) {
1932
- if (!interceptionDone) {
1933
- if (prop === "write") return patchedWrite;
1934
- if (prop === "visit") return patchedVisit;
1935
- if (prop === "append") return patchedAppend;
1775
+ experimentalGetLeftParenSourceRange: (node) => {
1776
+ const callLike = node;
1777
+ if (callLike.lParenRange) return {
1778
+ start: callLike.lParenRange[0],
1779
+ end: callLike.lParenRange[1]
1780
+ };
1781
+ return state.namedAttributeCalleeLParenRange.get(callLike.callee);
1936
1782
  }
1937
- const value = Reflect.get(target, prop);
1938
- if (typeof value === "function") return value.bind(target);
1939
- return value;
1940
- } }));
1941
- };
1942
- printer.CallExpression = newCallNewExpression;
1943
- printer.NewExpression = newCallNewExpression;
1944
- const prevWildcard = printer._;
1945
- printer._ = (node, context, visit) => {
1946
- const contextProto = Object.getPrototypeOf(context);
1947
- const prevContextWrite = contextProto.write;
1948
- if ("diagnosticsOnTop" in node && node.diagnosticsOnTop) contextProto.write = function(text, node) {
1949
- node ??= {};
1950
- node.loc ??= {
1951
- start: {
1952
- line: 1,
1953
- column: 0
1954
- },
1955
- end: {
1956
- line: 1,
1957
- column: 0
1958
- }
1959
- };
1960
- return prevContextWrite.call(this, text, node);
1961
1783
  };
1962
- prevWildcard(node, context, visit);
1963
- contextProto.write = prevContextWrite;
1964
- };
1965
- const patchedPrinter = printer;
1784
+ }
1966
1785
  //#endregion
1967
1786
  //#region src/transform/volar/index.ts
1968
- function gtsToTypings(ast, option) {
1787
+ function transformForVolar(ast, option, sourceInfo) {
1969
1788
  const state = {
1970
1789
  ...initialTranspileState(option),
1971
- leafTokens: option.leafTokens,
1972
1790
  idCounter: 0,
1973
1791
  typingPendingStatements: [],
1974
1792
  rootVmId: {
@@ -1996,25 +1814,37 @@ function gtsToTypings(ast, option) {
1996
1814
  metaTypeIdStack: [],
1997
1815
  finalMetaTypeIdStack: [],
1998
1816
  attrsOfCurrentVm: [],
1999
- extraMappings: option.extraMappings
2000
- };
2001
- const { code, map } = print(walk(ast, state, gtsToTypingsWalker), patchedPrinter, { indent: " " });
2002
- return {
2003
- code: applyReplacements(state, code),
2004
- sourceMap: map
1817
+ sourceNodes: /* @__PURE__ */ new WeakSet(),
1818
+ namedAttributeCalleeLParenRange: /* @__PURE__ */ new WeakMap(),
1819
+ literalFromIdentifier: /* @__PURE__ */ new WeakSet(),
1820
+ lastArgNodes: /* @__PURE__ */ new WeakSet(),
1821
+ diagnosticsOnTopNodes: /* @__PURE__ */ new WeakSet(),
1822
+ extraMappings: []
2005
1823
  };
2006
- }
2007
- function transformForVolar(ast, option, sourceInfo) {
2008
- const tokens = collectLeafTokens(ast);
2009
- const extraMappings = /* @__PURE__ */ new Map();
2010
- const { code, sourceMap } = gtsToTypings(ast, {
2011
- ...option,
2012
- leafTokens: tokens,
2013
- extraMappings
2014
- });
1824
+ walk(ast, state, { _(node, { state, next }) {
1825
+ if (node.range) state.sourceNodes.add(node);
1826
+ next();
1827
+ } });
1828
+ const newAst = walk(ast, state, gtsToTypingsWalker);
1829
+ walk(newAst, state, { CallExpression(node, { state }) {
1830
+ const lastArg = node.arguments.at(-1);
1831
+ if (lastArg) state.lastArgNodes.add(lastArg);
1832
+ } });
1833
+ let { code, mappings } = print$1(newAst, getPrintOptions(sourceInfo.content, state));
1834
+ code = applyReplacements(state, code, mappings);
1835
+ for (const extraMapping of state.extraMappings) {
1836
+ const genOffset = code.indexOf(extraMapping.generatedNeedle);
1837
+ mappings.push({
1838
+ sourceOffsets: [extraMapping.sourceOffset],
1839
+ lengths: [extraMapping.length],
1840
+ generatedOffsets: [genOffset],
1841
+ generatedLengths: [extraMapping.generatedNeedle.length],
1842
+ data: VERIFICATION_ONLY_MAPPING_DATA
1843
+ });
1844
+ }
2015
1845
  return {
2016
1846
  code,
2017
- mappings: convertToVolarMappings(code, sourceInfo.content, sourceMap, tokens, extraMappings)
1847
+ mappings
2018
1848
  };
2019
1849
  }
2020
1850
  //#endregion