@gi-tcg/gts-transpiler 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,11 @@
1
- // src/parse/index.ts
1
+ // packages/transpiler/src/parse/index.ts
2
2
  import { Parser } from "acorn";
3
3
  import { tsPlugin } from "@sveltejs/acorn-typescript";
4
4
 
5
- // src/parse/gts_plugin.ts
5
+ // packages/transpiler/src/parse/gts_plugin.ts
6
6
  import { tokTypes as tokTypes2 } from "acorn";
7
7
 
8
- // src/keywords.ts
8
+ // packages/transpiler/src/keywords.ts
9
9
  var specialIdentifiers = [
10
10
  "break",
11
11
  "case",
@@ -64,7 +64,7 @@ var specialIdentifiers = [
64
64
  "query"
65
65
  ];
66
66
 
67
- // src/parse/loose_plugin.ts
67
+ // packages/transpiler/src/parse/loose_plugin.ts
68
68
  import { tokTypes } from "acorn";
69
69
  var DUMMY_PLACEHOLDER = "✖";
70
70
  function loosePlugin() {
@@ -77,7 +77,7 @@ function loosePlugin() {
77
77
  return super.parseIdent(liberal);
78
78
  }
79
79
  };
80
- _proxiedThis = new Proxy(this, {
80
+ #proxiedThis = new Proxy(this, {
81
81
  get: (target, prop) => {
82
82
  if (prop === "parseIdent") {
83
83
  return this._patchedParseIdent;
@@ -96,13 +96,13 @@ function loosePlugin() {
96
96
  return this.finishNode(dummy, "Identifier");
97
97
  }
98
98
  parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
99
- return super.parseSubscript.call(this._proxiedThis, base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
99
+ return super.parseSubscript.call(this.#proxiedThis, base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
100
100
  }
101
101
  };
102
102
  };
103
103
  }
104
104
 
105
- // src/parse/gts_plugin.ts
105
+ // packages/transpiler/src/parse/gts_plugin.ts
106
106
  function gtsPlugin(options = {}) {
107
107
  return function gtsPluginTransformer(Parser) {
108
108
  const skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
@@ -137,13 +137,17 @@ function gtsPlugin(options = {}) {
137
137
  }
138
138
  gts_parseNamedAttributeDefinition() {
139
139
  const node = this.startNode();
140
+ const start = this.start;
140
141
  let name;
141
142
  if (this.type.label === "string") {
142
143
  name = this.parseExprAtom();
144
+ if (typeof name.value === "string" && name.value.startsWith("~")) {
145
+ this.raise(start, `Attribute name starts with '~' is reserved for internal use.`);
146
+ }
143
147
  } else if (this.type.label === "name") {
144
148
  name = this.parseIdent();
145
149
  } else {
146
- this.raise(this.start, "Expected attribute name");
150
+ this.raise(start, "Expected attribute name");
147
151
  }
148
152
  node.name = name;
149
153
  node.body = this.gts_parseAttributeBody();
@@ -299,7 +303,7 @@ function gtsPlugin(options = {}) {
299
303
  };
300
304
  }
301
305
 
302
- // src/parse/comment.js
306
+ // packages/transpiler/src/parse/comment.js
303
307
  import { walk } from "zimmerframe";
304
308
  function getCommentHandlers(source, comments, index = 0) {
305
309
  function getNextNonWhitespaceCharacter(text, startIndex) {
@@ -546,7 +550,7 @@ function getCommentHandlers(source, comments, index = 0) {
546
550
  };
547
551
  }
548
552
 
549
- // src/error.ts
553
+ // packages/transpiler/src/error.ts
550
554
  class GtsTranspilerError extends Error {
551
555
  position;
552
556
  constructor(message, position) {
@@ -556,7 +560,60 @@ class GtsTranspilerError extends Error {
556
560
  }
557
561
  }
558
562
 
559
- // src/parse/index.ts
563
+ // packages/transpiler/src/parse/record_call_lparen_plugin.ts
564
+ import { tokTypes as tokTypes3 } from "acorn";
565
+ function recordCallLParenPlugin() {
566
+ return function recordCallLParenPluginTransformer(parser) {
567
+ return class RecordCallLParenParser extends parser {
568
+ parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
569
+ let recordedLParenLoc = null;
570
+ if (!noCalls && this.type === tokTypes3.parenL) {
571
+ recordedLParenLoc = {
572
+ start: this.startLoc,
573
+ end: this.endLoc
574
+ };
575
+ }
576
+ const result = super.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
577
+ if (recordedLParenLoc && result.type === "CallExpression") {
578
+ result.lParenLoc = recordedLParenLoc;
579
+ }
580
+ return result;
581
+ }
582
+ _capturedLParenLocFromNew = null;
583
+ _patchedEat = (type) => {
584
+ if (type === tokTypes3.parenL) {
585
+ this._capturedLParenLocFromNew = {
586
+ start: this.startLoc,
587
+ end: this.endLoc
588
+ };
589
+ }
590
+ return this.eat(type);
591
+ };
592
+ #proxiedThis = new Proxy(this, {
593
+ get: (target, prop) => {
594
+ if (prop === "eat") {
595
+ return this._patchedEat;
596
+ }
597
+ const value = Reflect.get(target, prop);
598
+ if (typeof value === "function") {
599
+ return value.bind(target);
600
+ }
601
+ return value;
602
+ }
603
+ });
604
+ parseNew() {
605
+ const result = super.parseNew.apply(this.#proxiedThis);
606
+ if (this._capturedLParenLocFromNew && result.type === "NewExpression") {
607
+ result.lParenLoc = this._capturedLParenLocFromNew;
608
+ this._capturedLParenLocFromNew = null;
609
+ }
610
+ return result;
611
+ }
612
+ };
613
+ };
614
+ }
615
+
616
+ // packages/transpiler/src/parse/index.ts
560
617
  var TsParser = Parser.extend(tsPlugin());
561
618
  function parse(input, options) {
562
619
  try {
@@ -580,10 +637,9 @@ function parse(input, options) {
580
637
  }
581
638
  function parseLoose(input, options) {
582
639
  try {
583
- const GtsParser = TsParser.extend(loosePlugin(), gtsPlugin({
584
- ...options,
585
- allowEmptyShortcutMember: true,
586
- allowEmptyPositionalAttribute: true
640
+ const GtsParser = TsParser.extend(loosePlugin(), ...options?.recordCallLParens ? [recordCallLParenPlugin()] : [], gtsPlugin({
641
+ allowEmptyShortcutMember: options?.allowEmptyPositionalAttribute || true,
642
+ allowEmptyPositionalAttribute: options?.allowEmptyPositionalAttribute || true
587
643
  }));
588
644
  const { onComment, addComments } = getCommentHandlers(input, []);
589
645
  const ast = GtsParser.parse(input, {
@@ -607,7 +663,7 @@ function parseLoose(input, options) {
607
663
  }
608
664
  }
609
665
 
610
- // src/transform/erase_ts.ts
666
+ // packages/transpiler/src/transform/erase_ts.ts
611
667
  import { walk as walk2 } from "zimmerframe";
612
668
  var empty = {
613
669
  type: "EmptyStatement"
@@ -769,14 +825,14 @@ var eraseTs = (ast) => {
769
825
  return walk2(ast, null, eraseTsVisitor);
770
826
  };
771
827
 
772
- // src/transform/index.ts
828
+ // packages/transpiler/src/transform/index.ts
773
829
  import { print as print2 } from "esrap";
774
830
  import jsPrinter from "esrap/languages/ts";
775
831
 
776
- // src/transform/gts.ts
832
+ // packages/transpiler/src/transform/gts.ts
777
833
  import { walk as walk3 } from "zimmerframe";
778
834
 
779
- // src/transform/constants.ts
835
+ // packages/transpiler/src/transform/constants.ts
780
836
  var DEFAULT_SHORTCUT_FUNCTION_PRELUDES = [
781
837
  "cryo",
782
838
  "hydro",
@@ -789,33 +845,33 @@ var DEFAULT_SHORTCUT_FUNCTION_PRELUDES = [
789
845
  ];
790
846
  var DEFAULT_QUERY_BINDINGS = ["my", "opp"];
791
847
 
792
- // src/transform/gts.ts
848
+ // packages/transpiler/src/transform/gts.ts
793
849
  var commonGtsVisitor = {
794
850
  GTSDirectFunction(node, { visit, state }) {
795
851
  return {
796
- type: "ArrowFunctionExpression",
797
- params: [],
798
- body: {
799
- type: "ObjectExpression",
800
- properties: [
801
- {
802
- type: "Property",
803
- key: { type: "Identifier", name: "name" },
804
- computed: false,
805
- kind: "init",
806
- method: false,
807
- shorthand: false,
808
- value: state.ActionId,
809
- loc: node.loc
810
- },
811
- {
812
- type: "Property",
813
- key: { type: "Identifier", name: "positionals" },
814
- computed: false,
815
- kind: "init",
816
- method: false,
817
- shorthand: false,
818
- value: {
852
+ type: "ObjectExpression",
853
+ properties: [
854
+ {
855
+ type: "Property",
856
+ key: { type: "Identifier", name: "name" },
857
+ computed: false,
858
+ kind: "init",
859
+ method: false,
860
+ shorthand: false,
861
+ value: state.ActionLit,
862
+ loc: node.loc
863
+ },
864
+ {
865
+ type: "Property",
866
+ key: { type: "Identifier", name: "positionals" },
867
+ computed: false,
868
+ kind: "init",
869
+ method: false,
870
+ shorthand: false,
871
+ value: {
872
+ type: "ArrowFunctionExpression",
873
+ params: [],
874
+ body: {
819
875
  type: "ArrayExpression",
820
876
  elements: [
821
877
  {
@@ -828,23 +884,23 @@ var commonGtsVisitor = {
828
884
  expression: false
829
885
  }
830
886
  ]
831
- }
832
- },
833
- {
834
- type: "Property",
835
- key: { type: "Identifier", name: "named" },
836
- computed: false,
837
- kind: "init",
838
- method: false,
839
- shorthand: false,
840
- value: {
841
- type: "Literal",
842
- value: null
843
- }
887
+ },
888
+ expression: true
844
889
  }
845
- ]
846
- },
847
- expression: true,
890
+ },
891
+ {
892
+ type: "Property",
893
+ key: { type: "Identifier", name: "named" },
894
+ computed: false,
895
+ kind: "init",
896
+ method: false,
897
+ shorthand: false,
898
+ value: {
899
+ type: "Literal",
900
+ value: null
901
+ }
902
+ }
903
+ ],
848
904
  loc: node.loc
849
905
  };
850
906
  },
@@ -904,84 +960,14 @@ var commonGtsVisitor = {
904
960
  }
905
961
  };
906
962
  var gtsVisitor = {
907
- Program(node, { state, next }) {
908
- node = next() ?? node;
909
- const body = [...node.body];
910
- if (state.externalizedBindings.length > 0) {
911
- body.unshift({
912
- type: "ImportDeclaration",
913
- specifiers: [
914
- {
915
- type: "ImportDefaultSpecifier",
916
- local: state.binderFnId
917
- }
918
- ],
919
- source: {
920
- type: "Literal",
921
- value: `${state.providerImportSource}/binder`
922
- },
923
- attributes: []
924
- }, ...state.externalizedBindings.flatMap((binding) => {
925
- const internalDecl = {
926
- type: "VariableDeclaration",
927
- kind: "const",
928
- declarations: [
929
- {
930
- type: "VariableDeclarator",
931
- id: binding.internalId,
932
- init: binding.value
933
- }
934
- ]
935
- };
936
- const externalDecl = {
937
- type: "VariableDeclaration",
938
- kind: "const",
939
- declarations: [
940
- {
941
- type: "VariableDeclarator",
942
- id: binding.bindingName,
943
- init: {
944
- type: "CallExpression",
945
- optional: false,
946
- callee: state.binderFnId,
947
- arguments: [
948
- binding.internalId,
949
- {
950
- type: "ObjectExpression",
951
- properties: [
952
- {
953
- type: "Property",
954
- key: { type: "Identifier", name: "path" },
955
- computed: false,
956
- kind: "init",
957
- method: false,
958
- shorthand: false,
959
- value: {
960
- type: "ArrayExpression",
961
- elements: binding.path.map((segment) => ({
962
- type: "Literal",
963
- value: segment
964
- }))
965
- }
966
- }
967
- ]
968
- }
969
- ]
970
- }
971
- }
972
- ]
973
- };
974
- return binding.export ? [
975
- internalDecl,
976
- {
977
- type: "ExportNamedDeclaration",
978
- declaration: externalDecl,
979
- specifiers: [],
980
- attributes: []
981
- }
982
- ] : [internalDecl, externalDecl];
983
- }));
963
+ Program(node, { state, visit }) {
964
+ const body = [];
965
+ for (const stmt of node.body) {
966
+ const visited = visit(stmt);
967
+ body.push(visited);
984
968
  }
969
+ body.unshift(...state.bindingStatements);
970
+ state.bindingStatements = [];
985
971
  if (state.hasQueryExpressions) {
986
972
  body.unshift({
987
973
  type: "ImportDeclaration",
@@ -1008,17 +994,25 @@ var gtsVisitor = {
1008
994
  },
1009
995
  {
1010
996
  type: "ImportSpecifier",
1011
- imported: { type: "Identifier", name: "Action" },
1012
- local: state.ActionId
1013
- },
1014
- {
1015
- type: "ImportSpecifier",
1016
- imported: { type: "Identifier", name: "Prelude" },
1017
- local: state.preludeSymbolId
997
+ imported: { type: "Identifier", name: "createBinding" },
998
+ local: state.createBindingFnId
1018
999
  }
1019
1000
  ],
1020
1001
  source: { type: "Literal", value: state.runtimeImportSource },
1021
1002
  attributes: []
1003
+ }, {
1004
+ type: "ImportDeclaration",
1005
+ specifiers: [
1006
+ {
1007
+ type: "ImportDefaultSpecifier",
1008
+ local: state.rootVmId
1009
+ }
1010
+ ],
1011
+ source: {
1012
+ type: "Literal",
1013
+ value: `${state.providerImportSource}/vm`
1014
+ },
1015
+ attributes: []
1022
1016
  });
1023
1017
  return {
1024
1018
  ...node,
@@ -1026,42 +1020,90 @@ var gtsVisitor = {
1026
1020
  };
1027
1021
  },
1028
1022
  GTSDefineStatement(node, { state, visit }) {
1029
- const body = visit(node.body);
1030
- const wrapper = {
1031
- type: "ObjectExpression",
1032
- properties: [
1023
+ const defineId = state.defineIdCounter++;
1024
+ const rootAttr = visit(node.body);
1025
+ const nodeVarId = {
1026
+ type: "Identifier",
1027
+ name: `__gts_node_${defineId}`
1028
+ };
1029
+ const bindingsVarId = {
1030
+ type: "Identifier",
1031
+ name: `__gts_bindings_${defineId}`
1032
+ };
1033
+ const newBindings = state.externalizedBindings;
1034
+ state.externalizedBindings = [];
1035
+ state.bindingStatements.push({
1036
+ type: "VariableDeclaration",
1037
+ kind: "const",
1038
+ declarations: [
1033
1039
  {
1034
- type: "Property",
1035
- key: { type: "Identifier", name: "attributes" },
1036
- computed: false,
1037
- kind: "init",
1038
- method: false,
1039
- shorthand: false,
1040
- value: {
1041
- type: "ArrayExpression",
1042
- elements: [body]
1040
+ type: "VariableDeclarator",
1041
+ id: nodeVarId,
1042
+ init: rootAttr
1043
+ }
1044
+ ],
1045
+ loc: node.loc
1046
+ });
1047
+ state.bindingStatements.push({
1048
+ type: "VariableDeclaration",
1049
+ kind: "const",
1050
+ declarations: [
1051
+ {
1052
+ type: "VariableDeclarator",
1053
+ id: bindingsVarId,
1054
+ init: {
1055
+ type: "CallExpression",
1056
+ optional: false,
1057
+ callee: state.createBindingFnId,
1058
+ arguments: [state.rootVmId, nodeVarId]
1043
1059
  }
1044
1060
  }
1045
- ]
1046
- };
1061
+ ],
1062
+ loc: node.loc
1063
+ });
1064
+ for (let i = 0;i < newBindings.length; i++) {
1065
+ const binding = newBindings[i];
1066
+ const decl = {
1067
+ type: "VariableDeclaration",
1068
+ kind: "const",
1069
+ declarations: [
1070
+ {
1071
+ type: "VariableDeclarator",
1072
+ id: binding.bindingName,
1073
+ init: {
1074
+ type: "MemberExpression",
1075
+ object: bindingsVarId,
1076
+ property: { type: "Literal", value: i },
1077
+ computed: true,
1078
+ optional: false
1079
+ }
1080
+ }
1081
+ ]
1082
+ };
1083
+ if (binding.export) {
1084
+ state.bindingStatements.push({
1085
+ type: "ExportNamedDeclaration",
1086
+ declaration: decl,
1087
+ specifiers: [],
1088
+ attributes: []
1089
+ });
1090
+ } else {
1091
+ state.bindingStatements.push(decl);
1092
+ }
1093
+ }
1047
1094
  return {
1048
1095
  type: "ExpressionStatement",
1049
1096
  expression: {
1050
1097
  type: "CallExpression",
1051
1098
  optional: false,
1052
- callee: {
1053
- ...state.createDefineFnId,
1054
- loc: node.loc
1055
- },
1056
- arguments: [state.rootVmId, wrapper]
1099
+ callee: state.createDefineFnId,
1100
+ arguments: [state.rootVmId, nodeVarId]
1057
1101
  },
1058
1102
  loc: node.loc
1059
1103
  };
1060
1104
  },
1061
1105
  GTSNamedAttributeDefinition(node, { visit, state }) {
1062
- state.attributeNames.push(node.name);
1063
1106
  const namedBody = visit(node.body);
1064
- state.attributeNames.pop();
1065
1107
  const properties = [...namedBody.properties];
1066
1108
  const nameValue = node.name.type === "Literal" ? node.name : {
1067
1109
  ...node.name,
@@ -1082,39 +1124,29 @@ var gtsVisitor = {
1082
1124
  loc: node.loc
1083
1125
  });
1084
1126
  const body = { ...namedBody, properties };
1085
- const arrow = {
1086
- type: "ArrowFunctionExpression",
1087
- params: [],
1088
- expression: true,
1089
- body,
1090
- loc: node.loc
1091
- };
1092
1127
  if (node.bindingName) {
1093
1128
  if (node.bindingAccessModifier === "protected") {
1094
1129
  throw new GtsTranspilerError("Protected bindings are not supported in this context.", node.loc ?? null);
1095
1130
  }
1096
1131
  const export_ = node.bindingAccessModifier !== "private";
1097
- const internalId = {
1098
- type: "Identifier",
1099
- name: `__gts_internal_binding_${state.externalizedBindings.length}`
1100
- };
1101
1132
  state.externalizedBindings.push({
1102
1133
  bindingName: node.bindingName,
1103
- export: export_,
1104
- internalId,
1105
- value: arrow,
1106
- path: [...state.attributeNames, node.name].map((n) => {
1107
- if (n.type === "Literal") {
1108
- return String(n.value);
1109
- } else {
1110
- return n.name;
1111
- }
1112
- })
1134
+ export: export_
1135
+ });
1136
+ body.properties.push({
1137
+ type: "Property",
1138
+ key: { type: "Identifier", name: "binding" },
1139
+ computed: false,
1140
+ kind: "init",
1141
+ method: false,
1142
+ shorthand: false,
1143
+ value: {
1144
+ type: "Literal",
1145
+ value: export_ ? "public" : "private"
1146
+ }
1113
1147
  });
1114
- return internalId;
1115
- } else {
1116
- return arrow;
1117
1148
  }
1149
+ return body;
1118
1150
  },
1119
1151
  GTSAttributeBody(node, { visit }) {
1120
1152
  const positionals = visit(node.positionalAttributes);
@@ -1129,7 +1161,13 @@ var gtsVisitor = {
1129
1161
  kind: "init",
1130
1162
  method: false,
1131
1163
  shorthand: false,
1132
- value: positionals,
1164
+ value: {
1165
+ type: "ArrowFunctionExpression",
1166
+ params: [],
1167
+ body: positionals,
1168
+ expression: true,
1169
+ loc: positionals.loc
1170
+ },
1133
1171
  loc: positionals.loc
1134
1172
  },
1135
1173
  {
@@ -1194,9 +1232,9 @@ var initialTranspileState = (option = {}) => {
1194
1232
  const shortcutFunctionPreludes = option.shortcutFunctionPreludes ?? DEFAULT_SHORTCUT_FUNCTION_PRELUDES;
1195
1233
  const queryBindings = option.queryBindings ?? DEFAULT_QUERY_BINDINGS;
1196
1234
  const fnArgId = { type: "Identifier", name: "__gts_fnArg" };
1197
- const preludeSymbolId = {
1198
- type: "Identifier",
1199
- name: "__gts_Prelude"
1235
+ const PreludeLit = {
1236
+ type: "Literal",
1237
+ value: "~prelude"
1200
1238
  };
1201
1239
  const shortcutFunctionParameters = [
1202
1240
  fnArgId,
@@ -1217,7 +1255,7 @@ var initialTranspileState = (option = {}) => {
1217
1255
  right: {
1218
1256
  type: "MemberExpression",
1219
1257
  object: fnArgId,
1220
- property: preludeSymbolId,
1258
+ property: PreludeLit,
1221
1259
  computed: true,
1222
1260
  optional: false
1223
1261
  }
@@ -1239,12 +1277,12 @@ var initialTranspileState = (option = {}) => {
1239
1277
  ];
1240
1278
  return {
1241
1279
  createDefineFnId: { type: "Identifier", name: "__gts_createDefine" },
1242
- ActionId: { type: "Identifier", name: "__gts_Action" },
1243
- preludeSymbolId,
1280
+ createBindingFnId: { type: "Identifier", name: "__gts_createBinding" },
1281
+ ActionLit: { type: "Literal", value: "~action" },
1282
+ PreludeLit,
1244
1283
  fnArgId,
1245
1284
  shortcutFunctionParameters,
1246
1285
  rootVmId: { type: "Identifier", name: "__gts_rootVm" },
1247
- binderFnId: { type: "Identifier", name: "__gts_Binder" },
1248
1286
  queryFnId: { type: "Identifier", name: "__gts_query" },
1249
1287
  queryParameters,
1250
1288
  runtimeImportSource: option.runtimeImportSource ?? "@gi-tcg/gts-runtime",
@@ -1261,9 +1299,10 @@ var initialTranspileState = (option = {}) => {
1261
1299
  value: { type: "Identifier", name }
1262
1300
  }))
1263
1301
  },
1264
- attributeNames: [],
1265
1302
  externalizedBindings: [],
1266
- hasQueryExpressions: false
1303
+ hasQueryExpressions: false,
1304
+ defineIdCounter: 0,
1305
+ bindingStatements: []
1267
1306
  };
1268
1307
  };
1269
1308
  var gtsToTs = (ast, option = {}) => {
@@ -1271,12 +1310,11 @@ var gtsToTs = (ast, option = {}) => {
1271
1310
  return walk3(ast, state, gtsVisitor);
1272
1311
  };
1273
1312
 
1274
- // src/transform/volar/index.ts
1313
+ // packages/transpiler/src/transform/volar/index.ts
1275
1314
  import { walk as walk5 } from "zimmerframe";
1276
1315
  import { print } from "esrap";
1277
- import tsPrinter from "esrap/languages/ts";
1278
1316
 
1279
- // src/transform/volar/replacements.ts
1317
+ // packages/transpiler/src/transform/volar/replacements.ts
1280
1318
  var createReplacementHolder = (state, value) => {
1281
1319
  const rawValue = JSON.stringify(value);
1282
1320
  return {
@@ -1300,38 +1338,101 @@ var createReplacementHolder = (state, value) => {
1300
1338
  };
1301
1339
  function applyReplacements(state, code) {
1302
1340
  const replacementRegex = new RegExp("\\b" + state.replacementTag.name + "`(.*?)`", "gm");
1303
- const {
1304
- symbolsId: { NamedDefinition, Meta }
1305
- } = state;
1341
+ const { NamedDefinitionLit, MetaLit } = state;
1342
+ const NamedDefinition = JSON.stringify(NamedDefinitionLit.value);
1343
+ const Meta = JSON.stringify(MetaLit.value);
1344
+ const oneLine = (strings, ...values) => strings.reduce((result, chunk, index) => result + chunk + (index < values.length ? values[index] : ""), "").replace(/\n[ \t]*/g, " ").trim();
1306
1345
  return code.replace(replacementRegex, (_, rawPayload) => {
1307
1346
  const payload = JSON.parse(rawPayload);
1308
- if (payload.type === "enterVMFromRoot") {
1309
- return `type ${payload.defType} = (typeof ${payload.vm})[${NamedDefinition.name}]; type ${payload.metaType} = ${payload.defType}[${Meta.name}];`;
1347
+ if (payload.type === "preface") {
1348
+ return oneLine`
1349
+ namespace ${state.utilNsId.name} {
1350
+ export type UniqueKeyProbSegment = "__gts_unique_prob_seg__";
1351
+ export type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
1352
+ }
1353
+ `;
1354
+ } else if (payload.type === "enterVMFromRoot") {
1355
+ return oneLine`
1356
+ type ${payload.defType} = (typeof ${payload.vm})[${NamedDefinition}];
1357
+ type ${payload.metaType} = ${payload.defType}[${Meta}];
1358
+ `;
1310
1359
  } else if (payload.type === "enterVMFromAttr") {
1311
- return `type ${payload.defType} = ${payload.returnType} extends { namedDefinition: infer Def } ? Def : { [${Meta.name}]: unknown }; type ${payload.metaType} = ${payload.defType}[${Meta.name}];`;
1360
+ return oneLine`
1361
+ type ${payload.defType} = ${payload.returnType} extends { namedDefinition: infer Def } ? Def : { ${Meta}: unknown };
1362
+ type ${payload.metaType} = ${payload.defType}[${Meta}];
1363
+ `;
1312
1364
  } else if (payload.type === "exitVM") {
1313
1365
  const lhs = `${payload.finalMetaType}_lhs`;
1314
1366
  const requiredAttrsNs = `${payload.finalMetaType}_rans`;
1315
1367
  const collectedAttrsExpr = `${payload.collectedAttrs.join(" | ")}`;
1316
- const needleString = `null! as ${requiredAttrsNs}.RequiredAttributes`;
1368
+ const needleString = `"${requiredAttrsNs}_NeedleString" as any as "required attributes are missing"`;
1317
1369
  if (payload.errorLoc) {
1318
- state.additionalMappings.set(payload.errorLoc, needleString);
1370
+ state.extraMappings.set(payload.errorLoc, needleString);
1319
1371
  }
1320
- return `type ${payload.finalMetaType} = ${payload.metaType}; const ${lhs}: { [${Meta.name}]: ${payload.metaType} } & Omit<${payload.defType}, ${Meta.name}> = 0 as any; type ${lhs} = typeof ${lhs}; namespace ${requiredAttrsNs} { export type CollectedAttributes = ${collectedAttrsExpr}; export type RequiredAttributes = { [K in keyof ${payload.defType}]: ${lhs}[K] extends { required(this: ${lhs}): true } ? K : never }[keyof ${payload.defType}]; }; ((_: ${requiredAttrsNs}.CollectedAttributes) => 0)(${needleString});`;
1372
+ return oneLine`
1373
+ type ${payload.finalMetaType} = ${payload.metaType};
1374
+ let ${lhs}!: { ${Meta}: ${payload.metaType} } & Omit<${payload.defType}, ${Meta}>;
1375
+ type ${lhs} = typeof ${lhs};
1376
+ namespace ${requiredAttrsNs} {
1377
+ export type Collected = ${collectedAttrsExpr};
1378
+ export type Expected = { [K in keyof ${payload.defType}]: ${lhs}[K] extends { required(this: ${lhs}): true } ? K : never }[keyof ${payload.defType}];
1379
+ };
1380
+ ((_: ${requiredAttrsNs}.Expected extends ${requiredAttrsNs}.Collected ? string : ${requiredAttrsNs}.Expected) => 0)(${needleString});
1381
+ `;
1321
1382
  } else if (payload.type === "enterAttr") {
1322
- return `const ${payload.lhs}: { [${Meta.name}]: ${payload.metaType} } & Omit<${payload.defType}, ${Meta.name}> = 0 as any;`;
1383
+ const uniqueKeyLhs = `${payload.lhs}_uniqueKey_lhs`;
1384
+ const uniqueKey = `${payload.lhs}_uniqueKey`;
1385
+ const uniqueKeyForThis = `${payload.lhs}_uniqueKeyFor_${payload.lhs}`;
1386
+ const uniqueKeyHelperIntf = `${payload.defType}_uniqueKeyProbeHelper`;
1387
+ const omittedKeys = `${payload.lhs}_omittedKeys`;
1388
+ return oneLine`
1389
+ type ${uniqueKeyLhs} = {
1390
+ ${Meta}: ${payload.metaType};
1391
+ uniqueKey: ${payload.defType} extends { [${payload.attrName}]: { uniqueKey: infer UniqueKey } } ? UniqueKey : () => 0;
1392
+
1393
+ let ${uniqueKeyLhs}!: ${uniqueKeyLhs};
1394
+ let ${uniqueKey} = ${uniqueKeyLhs}.uniqueKey();
1395
+ type ${uniqueKey} = typeof ${uniqueKey};
1396
+ let ${uniqueKeyForThis}!: \`\${${uniqueKey}}\${${state.utilNsId.name}.UniqueKeyProbSegment}${payload.lhs}\`;
1397
+ interface ${uniqueKeyHelperIntf} {
1398
+ [${uniqueKeyForThis}]: 1;
1399
+ }
1400
+ type ${omittedKeys} = ${Meta} | (
1401
+ ${uniqueKey} extends 0
1402
+ ? never /* no unique requirement */
1403
+ : string extends keyof ${uniqueKeyHelperIntf}
1404
+ ? keyof ${payload.defType} /* too loose, disable all */
1405
+ : ${state.utilNsId.name}.UnionToIntersection<
1406
+ keyof ${uniqueKeyHelperIntf} & \`\${${uniqueKey}}\${${state.utilNsId.name}.UniqueKeyProbSegment}\${string}\`
1407
+ > extends never
1408
+ ? ${payload.attrName} /* have duplicate, disable this */
1409
+ : never
1410
+ );
1411
+ let ${payload.lhs}!: { ${Meta}: ${payload.metaType} } & Omit<${payload.defType}, ${omittedKeys}>;
1412
+ `;
1323
1413
  } else if (payload.type === "createBindingTyping") {
1324
1414
  const typingIdLhs = `${payload.typingId}_lhs`;
1325
- return `type ${typingIdLhs} = { [${Meta.name}]: ${payload.finalMetaType}; as: ${payload.defType}[${payload.attrName}] extends { as: infer As } ? As : unknown }; let ${typingIdLhs}!: ${typingIdLhs}; let ${payload.typingId} = ${typingIdLhs}.as(); type ${payload.typingId} = typeof ${payload.typingId};`;
1415
+ return oneLine`
1416
+ type ${typingIdLhs} = {
1417
+ ${Meta}: ${payload.finalMetaType};
1418
+ as: ${payload.defType} extends { [${payload.attrName}]: { as: infer As } } ? As : unknown;
1419
+ };
1420
+ let ${typingIdLhs}!: ${typingIdLhs};
1421
+ let ${payload.typingId} = ${typingIdLhs}.as();
1422
+ type ${payload.typingId} = typeof ${payload.typingId};
1423
+ `;
1326
1424
  } else if (payload.type === "exitAttr") {
1327
- return `type ${payload.returnType} = typeof ${payload.returnType}; type ${payload.newMetaType} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType}`;
1425
+ return oneLine`
1426
+ type ${payload.returnType} = typeof ${payload.returnType};
1427
+ type ${payload.newMetaType} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType}
1428
+ `;
1328
1429
  } else {
1329
1430
  return "";
1330
1431
  }
1331
1432
  });
1332
1433
  }
1333
1434
 
1334
- // src/transform/volar/walker.ts
1435
+ // packages/transpiler/src/transform/volar/walker.ts
1335
1436
  var EMPTY = { type: "EmptyStatement" };
1336
1437
  var ANY = {
1337
1438
  type: "TSAnyKeyword"
@@ -1341,59 +1442,7 @@ var ANY_INIT = {
1341
1442
  expression: { type: "Literal", value: 0 },
1342
1443
  typeAnnotation: ANY
1343
1444
  };
1344
- var emitPreface = (state) => {
1345
- if (state.prefaceInserted) {
1346
- return;
1347
- }
1348
- const symbolsLhs = {
1349
- type: "TSQualifiedName",
1350
- left: { type: "Identifier", name: state.rootVmId.name },
1351
- right: { type: "Identifier", name: "_symbols" }
1352
- };
1353
- for (const symbolName of [
1354
- "Meta",
1355
- "Action",
1356
- "NamedDefinition",
1357
- "Prelude"
1358
- ]) {
1359
- const init = {
1360
- type: "TSTypeQuery",
1361
- exprName: {
1362
- type: "TSQualifiedName",
1363
- left: symbolsLhs,
1364
- right: { type: "Identifier", name: symbolName }
1365
- }
1366
- };
1367
- const symbolId = symbolName === "Action" ? state.ActionId : symbolName === "Prelude" ? state.preludeSymbolId : state.symbolsId[symbolName];
1368
- state.pendingStatements.push({
1369
- type: "TSTypeAliasDeclaration",
1370
- id: symbolId,
1371
- typeAnnotation: init
1372
- }, {
1373
- type: "VariableDeclaration",
1374
- kind: "const",
1375
- declarations: [
1376
- {
1377
- type: "VariableDeclarator",
1378
- id: {
1379
- ...symbolId,
1380
- typeAnnotation: {
1381
- type: "TSTypeAnnotation",
1382
- typeAnnotation: {
1383
- type: "TSTypeReference",
1384
- typeName: symbolId
1385
- }
1386
- }
1387
- },
1388
- init: ANY_INIT
1389
- }
1390
- ]
1391
- });
1392
- }
1393
- state.prefaceInserted = true;
1394
- };
1395
1445
  var enterVMFromRoot = (state) => {
1396
- emitPreface(state);
1397
1446
  let defTypeId = {
1398
1447
  type: "Identifier",
1399
1448
  name: `__gts_rootVmDefType_${state.idCounter++}`
@@ -1406,7 +1455,7 @@ var enterVMFromRoot = (state) => {
1406
1455
  type: "Identifier",
1407
1456
  name: `__gts_rootVmFinalMetaType_${state.idCounter++}`
1408
1457
  };
1409
- state.pendingStatements.push(createReplacementHolder(state, {
1458
+ state.typingPendingStatements.push(createReplacementHolder(state, {
1410
1459
  type: "enterVMFromRoot",
1411
1460
  vm: state.rootVmId.name,
1412
1461
  defType: defTypeId.name,
@@ -1430,7 +1479,7 @@ var enterVMFromAttr = (state, returningId) => {
1430
1479
  type: "Identifier",
1431
1480
  name: `__gts_nestedVmFinalMetaType_${state.idCounter++}`
1432
1481
  };
1433
- state.pendingStatements.push(createReplacementHolder(state, {
1482
+ state.typingPendingStatements.push(createReplacementHolder(state, {
1434
1483
  type: "enterVMFromAttr",
1435
1484
  returnType: returningId.name,
1436
1485
  defType: defTypeId.name,
@@ -1446,7 +1495,7 @@ var exitVM = (state, errorLoc) => {
1446
1495
  const currentMetaId = state.metaTypeIdStack.pop();
1447
1496
  const finalMetaId = state.finalMetaTypeIdStack.pop();
1448
1497
  const collectedAttrNames = state.attrsOfCurrentVm.pop();
1449
- state.pendingStatements.push(createReplacementHolder(state, {
1498
+ state.typingPendingStatements.push(createReplacementHolder(state, {
1450
1499
  type: "exitVM",
1451
1500
  metaType: currentMetaId.name,
1452
1501
  defType: currentDefTypeId.name,
@@ -1466,11 +1515,12 @@ var enterAttr = (state, attrName) => {
1466
1515
  type: "Identifier",
1467
1516
  name: `__gts_attr_obj_${state.idCounter++}`
1468
1517
  };
1469
- state.pendingStatements.push(createReplacementHolder(state, {
1518
+ state.typingPendingStatements.push(createReplacementHolder(state, {
1470
1519
  type: "enterAttr",
1471
1520
  defType: defTypeId.name,
1472
1521
  metaType: metaTypeId.name,
1473
- lhs: lhsId.name
1522
+ lhs: lhsId.name,
1523
+ attrName
1474
1524
  }));
1475
1525
  return { lhsId };
1476
1526
  };
@@ -1480,7 +1530,7 @@ var genBindingTyping = (state, info) => {
1480
1530
  if (!finalMetaId || !defTypeId) {
1481
1531
  return;
1482
1532
  }
1483
- state.pendingStatements.push(createReplacementHolder(state, {
1533
+ state.typingPendingStatements.push(createReplacementHolder(state, {
1484
1534
  type: "createBindingTyping",
1485
1535
  finalMetaType: finalMetaId.name,
1486
1536
  defType: defTypeId.name,
@@ -1498,7 +1548,7 @@ var exitAttr = (state, returningId) => {
1498
1548
  name: `__gts_newMeta__${state.idCounter++}`
1499
1549
  };
1500
1550
  const [oldMetaTypeId] = state.metaTypeIdStack.splice(-1, 1, newMetaTypeId);
1501
- state.pendingStatements.push(createReplacementHolder(state, {
1551
+ state.typingPendingStatements.push(createReplacementHolder(state, {
1502
1552
  type: "exitAttr",
1503
1553
  defType: currentDefId.name,
1504
1554
  oldMetaType: oldMetaTypeId.name,
@@ -1513,113 +1563,49 @@ var gtsToTypingsWalker = {
1513
1563
  if (stmt.type === "GTSDefineStatement") {
1514
1564
  state.defineLeadingComments = stmt.leadingComments;
1515
1565
  visit(stmt);
1516
- body.push(...state.pendingStatements);
1517
- state.pendingStatements = [];
1566
+ body.push(...state.typingPendingStatements);
1567
+ state.typingPendingStatements = [];
1518
1568
  } else {
1519
1569
  body.push(visit(stmt));
1520
1570
  }
1521
1571
  }
1522
- if (state.externalizedBindings.length > 0) {
1523
- body.unshift({
1524
- type: "ImportDeclaration",
1525
- specifiers: [
1572
+ for (const extBinding of state.externalizedBindings) {
1573
+ const varDecl = {
1574
+ type: "VariableDeclaration",
1575
+ kind: "const",
1576
+ declarations: [
1526
1577
  {
1527
- type: "ImportDefaultSpecifier",
1528
- local: state.binderFnId
1529
- }
1530
- ],
1531
- source: {
1532
- type: "Literal",
1533
- value: `${state.providerImportSource}/binder`
1534
- },
1535
- attributes: []
1536
- }, ...state.externalizedBindings.flatMap((binding) => {
1537
- const internalDecl = {
1538
- type: "VariableDeclaration",
1539
- kind: "const",
1540
- declarations: [
1541
- {
1542
- type: "VariableDeclarator",
1543
- id: binding.internalId,
1544
- init: binding.value
1545
- }
1546
- ]
1547
- };
1548
- const externalDecl = {
1549
- type: "VariableDeclaration",
1550
- kind: "const",
1551
- declarations: [
1552
- {
1553
- type: "VariableDeclarator",
1554
- id: binding.bindingName,
1555
- init: {
1556
- type: "CallExpression",
1557
- optional: false,
1558
- callee: state.binderFnId,
1559
- arguments: [
1560
- binding.internalId,
1561
- {
1562
- type: "ObjectExpression",
1563
- properties: [
1564
- {
1565
- type: "Property",
1566
- key: { type: "Identifier", name: "path" },
1567
- computed: false,
1568
- kind: "init",
1569
- method: false,
1570
- shorthand: false,
1571
- value: {
1572
- type: "ArrayExpression",
1573
- elements: binding.path.map((segment) => ({
1574
- type: "Literal",
1575
- value: segment
1576
- }))
1577
- }
1578
- }
1579
- ]
1580
- }
1581
- ]
1578
+ type: "VariableDeclarator",
1579
+ id: extBinding.bindingName,
1580
+ init: ANY_INIT,
1581
+ typeAnnotation: {
1582
+ type: "TSTypeAnnotation",
1583
+ typeAnnotation: {
1584
+ type: "TSTypeReference",
1585
+ typeName: extBinding.typingId
1582
1586
  }
1583
1587
  }
1584
- ]
1585
- };
1586
- return binding.export ? [
1587
- internalDecl,
1588
- {
1589
- type: "ExportNamedDeclaration",
1590
- declaration: externalDecl,
1591
- specifiers: [],
1592
- attributes: [],
1593
- leadingComments: binding.leadingComments
1594
1588
  }
1595
- ] : [
1596
- internalDecl,
1597
- {
1598
- ...externalDecl,
1599
- leadingComments: binding.leadingComments
1600
- }
1601
- ];
1602
- }));
1603
- }
1604
- if (state.prefaceInserted) {
1605
- body.unshift({
1606
- type: "ImportDeclaration",
1607
- specifiers: [
1608
- {
1609
- type: "ImportDefaultSpecifier",
1610
- local: state.rootVmId
1611
- }
1612
- ],
1613
- source: {
1614
- type: "Literal",
1615
- value: `${state.providerImportSource}/rootVM`
1616
- },
1617
- attributes: []
1618
- });
1589
+ ]
1590
+ };
1591
+ if (extBinding.export) {
1592
+ body.unshift({
1593
+ type: "ExportNamedDeclaration",
1594
+ declaration: varDecl,
1595
+ specifiers: [],
1596
+ source: null,
1597
+ attributes: [],
1598
+ leadingComments: extBinding.leadingComments
1599
+ });
1600
+ } else {
1601
+ varDecl.leadingComments = extBinding.leadingComments;
1602
+ body.unshift(varDecl);
1603
+ }
1619
1604
  }
1620
1605
  if (state.hasQueryExpressions) {
1621
1606
  body.unshift({
1622
1607
  type: "ImportDeclaration",
1608
+ diagnosticsOnTop: true,
1623
1609
  specifiers: [
1624
1610
  {
1625
1611
  type: "ImportDefaultSpecifier",
@@ -1633,6 +1619,23 @@ var gtsToTypingsWalker = {
1633
1619
  attributes: []
1634
1620
  });
1635
1621
  }
1622
+ body.unshift({
1623
+ type: "ImportDeclaration",
1624
+ diagnosticsOnTop: true,
1625
+ specifiers: [
1626
+ {
1627
+ type: "ImportDefaultSpecifier",
1628
+ local: state.rootVmId
1629
+ }
1630
+ ],
1631
+ source: {
1632
+ type: "Literal",
1633
+ value: `${state.providerImportSource}/vm`
1634
+ },
1635
+ attributes: []
1636
+ }, createReplacementHolder(state, {
1637
+ type: "preface"
1638
+ }));
1636
1639
  return {
1637
1640
  ...node,
1638
1641
  body
@@ -1647,15 +1650,18 @@ var gtsToTypingsWalker = {
1647
1650
  GTSNamedAttributeDefinition(node, { visit, state }) {
1648
1651
  const { name, body, bindingName } = node;
1649
1652
  const attrName = JSON.stringify(name.type === "Literal" ? String(name.value) : name.name);
1653
+ const attributeNameToken = state.leafTokens.find((t) => t.loc === name.loc);
1654
+ if (attributeNameToken) {
1655
+ attributeNameToken.sourceLengthOffset = 1;
1656
+ }
1650
1657
  const { lhsId } = enterAttr(state, attrName);
1658
+ state.extraMappings.set(`${name.loc?.start.line}:${name.loc?.start.column}`, `${lhsId.name}${name.type === "Literal" ? `[` : `.`}`);
1651
1659
  const positionals = body.positionalAttributes.attributes.map((attr) => {
1652
1660
  if (attr.type === "Identifier" && /^[a-z_]/.test(attr.name)) {
1653
1661
  const token = state.leafTokens.find((t) => t.loc === attr.loc);
1654
1662
  if (token) {
1655
- token.locationAdjustment = {
1656
- startOffset: 1,
1657
- generatedLength: attr.name.length + 2
1658
- };
1663
+ token.generatedStartOffset = 1;
1664
+ token.generatedLength = attr.name.length + 2;
1659
1665
  }
1660
1666
  return {
1661
1667
  type: "Literal",
@@ -1670,7 +1676,7 @@ var gtsToTypingsWalker = {
1670
1676
  type: "Identifier",
1671
1677
  name: `__gts_attrRet_${state.idCounter++}`
1672
1678
  };
1673
- state.pendingStatements.push({
1679
+ state.typingPendingStatements.push({
1674
1680
  type: "VariableDeclaration",
1675
1681
  kind: "const",
1676
1682
  declarations: [
@@ -1699,10 +1705,6 @@ var gtsToTypingsWalker = {
1699
1705
  }
1700
1706
  if (bindingName) {
1701
1707
  const export_ = node.bindingAccessModifier !== "private";
1702
- const internalId = {
1703
- type: "Identifier",
1704
- name: `__gts_internal_binding_${state.externalizedBindings.length}`
1705
- };
1706
1708
  const typingId = {
1707
1709
  type: "Identifier",
1708
1710
  name: `gts_binding_type_${state.externalizedBindings.length}`
@@ -1723,15 +1725,6 @@ var gtsToTypingsWalker = {
1723
1725
  }
1724
1726
  },
1725
1727
  export: export_,
1726
- internalId,
1727
- value: { type: "Literal", value: null },
1728
- path: [...state.attributeNames, node.name].map((n) => {
1729
- if (n.type === "Literal") {
1730
- return String(n.value);
1731
- } else {
1732
- return n.name;
1733
- }
1734
- }),
1735
1728
  typingId,
1736
1729
  leadingComments: state.defineLeadingComments
1737
1730
  });
@@ -1744,7 +1737,11 @@ var gtsToTypingsWalker = {
1744
1737
  visit(attr);
1745
1738
  }
1746
1739
  if (node.directAction) {
1747
- const { lhsId } = enterAttr(state, state.ActionId.name);
1740
+ const attrName = JSON.stringify(state.ActionLit.value);
1741
+ const { lhsId } = enterAttr(state, attrName);
1742
+ const actionNotExistsReplacementStr = `${lhsId.name}[${attrName}]`;
1743
+ const actionNotExistsErrorLoc = `${node.directAction.loc?.start.line}:${node.directAction.loc?.start.column}`;
1744
+ state.extraMappings.set(actionNotExistsErrorLoc, actionNotExistsReplacementStr);
1748
1745
  const fn = {
1749
1746
  type: "ArrowFunctionExpression",
1750
1747
  params: state.shortcutFunctionParameters,
@@ -1758,7 +1755,7 @@ var gtsToTypingsWalker = {
1758
1755
  type: "Identifier",
1759
1756
  name: `__gts_attrRet_${state.idCounter++}`
1760
1757
  };
1761
- state.pendingStatements.push({
1758
+ state.typingPendingStatements.push({
1762
1759
  type: "VariableDeclaration",
1763
1760
  kind: "const",
1764
1761
  declarations: [
@@ -1771,7 +1768,7 @@ var gtsToTypingsWalker = {
1771
1768
  callee: {
1772
1769
  type: "MemberExpression",
1773
1770
  object: lhsId,
1774
- property: state.ActionId,
1771
+ property: state.ActionLit,
1775
1772
  computed: true,
1776
1773
  optional: false
1777
1774
  },
@@ -1796,7 +1793,7 @@ var gtsToTypingsWalker = {
1796
1793
  }
1797
1794
  };
1798
1795
 
1799
- // src/transform/volar/mappings.ts
1796
+ // packages/transpiler/src/transform/volar/mappings.ts
1800
1797
  import { decode } from "@jridgewell/sourcemap-codec";
1801
1798
  var DEFAULT_VOLAR_MAPPING_DATA = {
1802
1799
  completion: true,
@@ -1870,8 +1867,7 @@ function buildSrcToGenMap(source_map, line_offsets, generated_code) {
1870
1867
  function getGeneratedPosition(src_line, src_column, srcToGenMap) {
1871
1868
  const key = `${src_line}:${src_column}`;
1872
1869
  const positions = srcToGenMap.get(key);
1873
- if (!positions || positions.length === 0) {}
1874
- return positions?.[0];
1870
+ return positions || [];
1875
1871
  }
1876
1872
  function createLineOffsets(content) {
1877
1873
  const lines = content.split(`
@@ -1888,39 +1884,41 @@ function locToOffset(line, column, line_offsets) {
1888
1884
  if (line < 1 || line > line_offsets.length) {}
1889
1885
  return line_offsets[line - 1] + column;
1890
1886
  }
1891
- function convertToVolarMappings(generated, source, sourceMap, tokens, additionalMappings) {
1887
+ function convertToVolarMappings(generated, source, sourceMap, tokens, extraMappings) {
1892
1888
  const sourceLineOffsets = createLineOffsets(source);
1893
1889
  const generatedLineOffsets = createLineOffsets(generated);
1894
1890
  const srcToGenMap = buildSrcToGenMap(sourceMap, generatedLineOffsets, generated);
1895
1891
  const mappings = [];
1896
1892
  for (const token of tokens) {
1897
1893
  let sourceStart = locToOffset(token.loc.start.line, token.loc.start.column, sourceLineOffsets);
1894
+ sourceStart += token.sourceStartOffset ?? 0;
1898
1895
  const sourceEnd = locToOffset(token.loc.end.line, token.loc.end.column, sourceLineOffsets);
1899
1896
  let sourceLength = token.sourceLength ?? sourceEnd - sourceStart;
1900
- const genLineCol = getGeneratedPosition(token.loc.start.line, token.loc.start.column, srcToGenMap);
1897
+ sourceLength += token.sourceLengthOffset ?? 0;
1898
+ const [genLineCol] = getGeneratedPosition(token.loc.start.line, token.loc.start.column, srcToGenMap);
1901
1899
  if (!genLineCol) {
1902
1900
  continue;
1903
1901
  }
1904
1902
  let genStart = locToOffset(genLineCol.line, genLineCol.column, generatedLineOffsets);
1905
- if (token.locationAdjustment) {
1903
+ if (token.isDummy) {
1904
+ while (sourceStart > 0 && /\s/.test(source[sourceStart - 1])) {
1905
+ sourceStart--;
1906
+ sourceLength++;
1907
+ }
1908
+ }
1909
+ const generatedLength = token.generatedLength ?? sourceLength;
1910
+ if (typeof token.generatedStartOffset === "number" && token.generatedStartOffset > 0) {
1906
1911
  mappings.push({
1907
1912
  sourceOffsets: [sourceStart],
1908
1913
  generatedOffsets: [genStart],
1909
1914
  lengths: [0],
1910
- generatedLengths: [token.locationAdjustment.generatedLength],
1915
+ generatedLengths: [generatedLength],
1911
1916
  data: {
1912
1917
  verification: true
1913
1918
  }
1914
1919
  });
1915
- genStart += token.locationAdjustment.startOffset;
1920
+ genStart += token.generatedStartOffset;
1916
1921
  }
1917
- if (token.isDummy) {
1918
- while (sourceStart > 0 && /\s/.test(source[sourceStart - 1])) {
1919
- sourceStart--;
1920
- sourceLength++;
1921
- }
1922
- }
1923
- const generatedLength = token.generatedLength ?? sourceLength;
1924
1922
  mappings.push({
1925
1923
  sourceOffsets: [sourceStart],
1926
1924
  generatedOffsets: [genStart],
@@ -1929,7 +1927,20 @@ function convertToVolarMappings(generated, source, sourceMap, tokens, additional
1929
1927
  data: DEFAULT_VOLAR_MAPPING_DATA
1930
1928
  });
1931
1929
  }
1932
- for (const [loc, codeSnippet] of additionalMappings) {
1930
+ const locMapsToTop = getGeneratedPosition(1, 0, srcToGenMap);
1931
+ for (const loc of locMapsToTop) {
1932
+ const offset = locToOffset(loc.line, loc.column, generatedLineOffsets);
1933
+ mappings.push({
1934
+ sourceOffsets: [0],
1935
+ generatedOffsets: [offset],
1936
+ lengths: [0],
1937
+ generatedLengths: [0],
1938
+ data: {
1939
+ verification: true
1940
+ }
1941
+ });
1942
+ }
1943
+ for (const [loc, codeSnippet] of extraMappings) {
1933
1944
  const generatedStart = generated.indexOf(codeSnippet);
1934
1945
  if (generatedStart === -1) {
1935
1946
  continue;
@@ -1954,7 +1965,7 @@ function convertToVolarMappings(generated, source, sourceMap, tokens, additional
1954
1965
  return mappings;
1955
1966
  }
1956
1967
 
1957
- // src/transform/volar/collect_tokens.ts
1968
+ // packages/transpiler/src/transform/volar/collect_tokens.ts
1958
1969
  import { walk as walk4 } from "zimmerframe";
1959
1970
  function isLeafNode(node) {
1960
1971
  for (const key in node) {
@@ -1972,60 +1983,159 @@ function isLeafNode(node) {
1972
1983
  return true;
1973
1984
  }
1974
1985
  function collectLeafTokens(ast) {
1975
- const tokens = [];
1976
- walk4(ast, tokens, {
1977
- _(node, { state, next }) {
1986
+ const state = {
1987
+ tokens: []
1988
+ };
1989
+ walk4(ast, state, {
1990
+ _(node, { state: state2, next }) {
1978
1991
  if (isLeafNode(node) && node.loc) {
1979
1992
  const token = {
1980
1993
  loc: node.loc
1981
1994
  };
1982
- if (node.isDummy) {
1995
+ if ("isDummy" in node && node.isDummy) {
1983
1996
  token.isDummy = true;
1984
1997
  token.sourceLength = 0;
1985
1998
  token.generatedLength = 1;
1986
1999
  }
1987
- state.push(token);
2000
+ state2.tokens.push(token);
2001
+ }
2002
+ next();
2003
+ },
2004
+ NewExpression(node, { state: state2, next }) {
2005
+ const lParenLoc = node.lParenLoc;
2006
+ if (lParenLoc) {
2007
+ state2.tokens.push({
2008
+ loc: lParenLoc
2009
+ });
2010
+ }
2011
+ next();
2012
+ },
2013
+ CallExpression(node, { state: state2, next }) {
2014
+ const lParenLoc = node.lParenLoc;
2015
+ if (lParenLoc) {
2016
+ state2.tokens.push({
2017
+ loc: lParenLoc
2018
+ });
1988
2019
  }
1989
2020
  next();
1990
2021
  }
1991
2022
  });
1992
- return tokens;
2023
+ return state.tokens;
1993
2024
  }
1994
2025
 
1995
- // src/transform/volar/index.ts
2026
+ // packages/transpiler/src/transform/volar/printer.ts
2027
+ import tsPrinter from "esrap/languages/ts";
2028
+ var printer = tsPrinter({
2029
+ getLeadingComments: (node) => node.leadingComments,
2030
+ getTrailingComments: (node) => node.trailingComments
2031
+ });
2032
+ var prevIdentifier = printer.Identifier;
2033
+ printer.Identifier = function(node, context) {
2034
+ if (node.isDummy) {
2035
+ const text = Reflect.get(node, "lastArg") ? "," : "";
2036
+ context.write(text, node);
2037
+ } else {
2038
+ prevIdentifier(node, context);
2039
+ }
2040
+ };
2041
+ var prevCallNewExpression = printer.CallExpression;
2042
+ var newCallNewExpression = function(node, context) {
2043
+ const lastArg = node.arguments.at(-1);
2044
+ if (lastArg) {
2045
+ Reflect.set(lastArg, "lastArg", true);
2046
+ }
2047
+ if (!node.lParenLoc) {
2048
+ return prevCallNewExpression(node, context);
2049
+ }
2050
+ let hasDeferredWrite = false;
2051
+ let interceptionDone = false;
2052
+ const lParenFakeNode = {
2053
+ loc: node.lParenLoc
2054
+ };
2055
+ const patchedWrite = (text, node2) => {
2056
+ if (text === "(") {
2057
+ hasDeferredWrite = true;
2058
+ } else {
2059
+ context.write(text, node2);
2060
+ }
2061
+ };
2062
+ const patchedVisit = (node2) => {
2063
+ if (hasDeferredWrite) {
2064
+ context.write("(");
2065
+ }
2066
+ return context.visit(node2);
2067
+ };
2068
+ const patchedAppend = (subcontext) => {
2069
+ if (hasDeferredWrite) {
2070
+ context.write("(", lParenFakeNode);
2071
+ interceptionDone = true;
2072
+ }
2073
+ return context.append(subcontext);
2074
+ };
2075
+ const proxiedContext = new Proxy(context, {
2076
+ get(target, prop) {
2077
+ if (!interceptionDone) {
2078
+ if (prop === "write") {
2079
+ return patchedWrite;
2080
+ }
2081
+ if (prop === "visit") {
2082
+ return patchedVisit;
2083
+ }
2084
+ if (prop === "append") {
2085
+ return patchedAppend;
2086
+ }
2087
+ }
2088
+ const value = Reflect.get(target, prop);
2089
+ if (typeof value === "function") {
2090
+ return value.bind(target);
2091
+ }
2092
+ return value;
2093
+ }
2094
+ });
2095
+ return prevCallNewExpression(node, proxiedContext);
2096
+ };
2097
+ printer.CallExpression = newCallNewExpression;
2098
+ printer.NewExpression = newCallNewExpression;
2099
+ var prevWildcard = printer._;
2100
+ printer._ = (node, context, visit) => {
2101
+ const contextProto = Object.getPrototypeOf(context);
2102
+ const prevContextWrite = contextProto.write;
2103
+ if ("diagnosticsOnTop" in node && node.diagnosticsOnTop) {
2104
+ contextProto.write = function(text, node2) {
2105
+ node2 ??= {};
2106
+ node2.loc ??= {
2107
+ start: { line: 1, column: 0 },
2108
+ end: { line: 1, column: 0 }
2109
+ };
2110
+ return prevContextWrite.call(this, text, node2);
2111
+ };
2112
+ }
2113
+ prevWildcard(node, context, visit);
2114
+ contextProto.write = prevContextWrite;
2115
+ };
2116
+ var patchedPrinter = printer;
2117
+
2118
+ // packages/transpiler/src/transform/volar/index.ts
1996
2119
  function gtsToTypings(ast, option) {
1997
2120
  const state = {
1998
2121
  ...initialTranspileState(option),
1999
2122
  leafTokens: option.leafTokens,
2000
2123
  idCounter: 0,
2001
- pendingStatements: [],
2002
- prefaceInserted: false,
2003
- rootVmId: { type: "Identifier", name: "__root_vm" },
2124
+ typingPendingStatements: [],
2125
+ rootVmId: { type: "Identifier", name: "__gts_root_vm" },
2126
+ utilNsId: { type: "Identifier", name: "__gts_util" },
2004
2127
  replacementTag: { type: "Identifier", name: "__gts_replacement_tag" },
2005
- symbolsId: {
2006
- Meta: { type: "Identifier", name: "__gts_symbols_meta" },
2007
- NamedDefinition: { type: "Identifier", name: "__gts_symbols_namedDef" }
2008
- },
2128
+ MetaLit: { type: "Literal", value: "~meta" },
2129
+ NamedDefinitionLit: { type: "Literal", value: "~namedDefinition" },
2130
+ defineLeadingComments: [],
2009
2131
  vmDefTypeIdStack: [],
2010
2132
  metaTypeIdStack: [],
2011
2133
  finalMetaTypeIdStack: [],
2012
2134
  attrsOfCurrentVm: [],
2013
- additionalMappings: option.additionalMappings
2135
+ extraMappings: option.extraMappings
2014
2136
  };
2015
2137
  const newAst = walk5(ast, state, gtsToTypingsWalker);
2016
- const printer = tsPrinter({
2017
- getLeadingComments: (node) => node.leadingComments,
2018
- getTrailingComments: (node) => node.trailingComments
2019
- });
2020
- const prevIdentifier = printer.Identifier;
2021
- printer.Identifier = function(node, context) {
2022
- if (node.isDummy) {
2023
- context.write("", node);
2024
- } else {
2025
- prevIdentifier(node, context);
2026
- }
2027
- };
2028
- const { code, map } = print(newAst, printer, {
2138
+ const { code, map } = print(newAst, patchedPrinter, {
2029
2139
  indent: " "
2030
2140
  });
2031
2141
  return {
@@ -2035,20 +2145,20 @@ function gtsToTypings(ast, option) {
2035
2145
  }
2036
2146
  function transformForVolar(ast, option, sourceInfo) {
2037
2147
  const tokens = collectLeafTokens(ast);
2038
- const additionalMappings = new Map;
2148
+ const extraMappings = new Map;
2039
2149
  const { code, sourceMap } = gtsToTypings(ast, {
2040
2150
  ...option,
2041
2151
  leafTokens: tokens,
2042
- additionalMappings
2152
+ extraMappings
2043
2153
  });
2044
- const volarMappings = convertToVolarMappings(code, sourceInfo.content, sourceMap, tokens, additionalMappings);
2154
+ const volarMappings = convertToVolarMappings(code, sourceInfo.content, sourceMap, tokens, extraMappings);
2045
2155
  return {
2046
2156
  code,
2047
2157
  mappings: volarMappings
2048
2158
  };
2049
2159
  }
2050
2160
 
2051
- // src/transform/index.ts
2161
+ // packages/transpiler/src/transform/index.ts
2052
2162
  function transform(ast, option = {}, sourceInfo = {}) {
2053
2163
  const ts = gtsToTs(ast, option);
2054
2164
  const js = eraseTs(ts);
@@ -2062,8 +2172,160 @@ function transform(ast, option = {}, sourceInfo = {}) {
2062
2172
  sourceMap: map
2063
2173
  };
2064
2174
  }
2175
+ // packages/transpiler/src/config.ts
2176
+ var path = globalThis.require ? globalThis.require("node:path") : {
2177
+ isAbsolute(filePath) {
2178
+ return filePath.startsWith("/");
2179
+ },
2180
+ dirname(filePath) {
2181
+ if (!filePath) {
2182
+ return ".";
2183
+ }
2184
+ const normalized = normalizeSlashes(filePath);
2185
+ if (normalized === "/") {
2186
+ return "/";
2187
+ }
2188
+ const trimmed = normalized.length > 1 && normalized.endsWith("/") ? normalized.slice(0, -1) : normalized;
2189
+ const idx = trimmed.lastIndexOf("/");
2190
+ if (idx < 0) {
2191
+ return ".";
2192
+ }
2193
+ if (idx === 0) {
2194
+ return "/";
2195
+ }
2196
+ return trimmed.slice(0, idx);
2197
+ },
2198
+ resolve(...segments) {
2199
+ if (segments.length === 0) {
2200
+ return ".";
2201
+ }
2202
+ let resolved = "";
2203
+ for (let i = segments.length - 1;i >= 0; i--) {
2204
+ const segment = segments[i];
2205
+ if (!segment) {
2206
+ continue;
2207
+ }
2208
+ if (resolved) {
2209
+ resolved = `${segment}/${resolved}`;
2210
+ } else {
2211
+ resolved = segment;
2212
+ }
2213
+ if (path.isAbsolute(segment)) {
2214
+ break;
2215
+ }
2216
+ }
2217
+ return normalizeResolvedPath(resolved || ".");
2218
+ }
2219
+ };
2220
+ function normalizeSlashes(filePath) {
2221
+ return filePath.replace(/\\+/g, "/");
2222
+ }
2223
+ function normalizeResolvedPath(filePath) {
2224
+ const normalized = normalizeSlashes(filePath);
2225
+ const isAbsolute = normalized.startsWith("/");
2226
+ const parts = normalized.split("/");
2227
+ const stack = [];
2228
+ for (const part of parts) {
2229
+ if (!part || part === ".") {
2230
+ continue;
2231
+ }
2232
+ if (part === "..") {
2233
+ if (stack.length > 0 && stack[stack.length - 1] !== "..") {
2234
+ stack.pop();
2235
+ } else if (!isAbsolute) {
2236
+ stack.push("..");
2237
+ }
2238
+ continue;
2239
+ }
2240
+ stack.push(part);
2241
+ }
2242
+ if (isAbsolute) {
2243
+ return `/${stack.join("/")}` || "/";
2244
+ }
2245
+ return stack.join("/") || ".";
2246
+ }
2247
+ var DEFAULT_GTS_CONFIG = {
2248
+ runtimeImportSource: "@gi-tcg/gts-runtime",
2249
+ providerImportSource: "@gi-tcg/core/gts",
2250
+ shortcutFunctionPreludes: [
2251
+ "cryo",
2252
+ "hydro",
2253
+ "pyro",
2254
+ "electro",
2255
+ "anemo",
2256
+ "geo",
2257
+ "dendro",
2258
+ "omni"
2259
+ ],
2260
+ queryBindings: ["my", "opp"]
2261
+ };
2262
+ function* resolveGtsConfigImpl(filePath, inlineConfig = {}, options) {
2263
+ const startDir = normalizeStartDir(filePath, options.cwd);
2264
+ const stopDir = options.stopDir ? path.resolve(options.stopDir) : undefined;
2265
+ const pkgConfig = yield* findNearestPackageConfig(options.readFileFn, startDir, stopDir);
2266
+ return {
2267
+ ...DEFAULT_GTS_CONFIG,
2268
+ ...pkgConfig,
2269
+ ...inlineConfig
2270
+ };
2271
+ }
2272
+ async function resolveGtsConfig(filePath, inlineConfig, options) {
2273
+ const generator = resolveGtsConfigImpl(filePath, inlineConfig, options);
2274
+ let result = generator.next();
2275
+ while (!result.done) {
2276
+ const toRead = result.value;
2277
+ const content = await toRead;
2278
+ result = generator.next(content);
2279
+ }
2280
+ return result.value;
2281
+ }
2282
+ function resolveGtsConfigSync(filePath, inlineConfig, options) {
2283
+ const generator = resolveGtsConfigImpl(filePath, inlineConfig, options);
2284
+ let result = generator.next();
2285
+ while (!result.done) {
2286
+ const toRead = result.value;
2287
+ if (toRead instanceof Promise) {
2288
+ throw new Error("resolveGtsConfigSync received a Promise. Did you mean to use resolveGtsConfig instead?");
2289
+ }
2290
+ const content = toRead;
2291
+ result = generator.next(content);
2292
+ }
2293
+ return result.value;
2294
+ }
2295
+ function normalizeStartDir(sourceFile, cwd) {
2296
+ const absolute = path.isAbsolute(sourceFile) ? sourceFile : path.resolve(cwd || ".", sourceFile);
2297
+ return path.dirname(absolute);
2298
+ }
2299
+ function* findNearestPackageConfig(readFileFn, startDir, stopDir) {
2300
+ let currentDir = startDir;
2301
+ while (true) {
2302
+ const pkgPath = path.resolve(currentDir, "package.json");
2303
+ const config = yield* readPackageConfig(readFileFn, pkgPath);
2304
+ if (config) {
2305
+ return config;
2306
+ }
2307
+ const parentDir = path.dirname(currentDir);
2308
+ if (parentDir === currentDir) {
2309
+ break;
2310
+ }
2311
+ if (stopDir && currentDir === stopDir) {
2312
+ break;
2313
+ }
2314
+ currentDir = parentDir;
2315
+ }
2316
+ return {};
2317
+ }
2318
+ function* readPackageConfig(readFileFn, pkgPath) {
2319
+ try {
2320
+ const content = yield readFileFn(pkgPath, "utf8");
2321
+ const parsed = JSON.parse(content);
2322
+ return parsed.gamingTs;
2323
+ } catch {
2324
+ return;
2325
+ }
2326
+ }
2065
2327
 
2066
- // src/index.ts
2328
+ // packages/transpiler/src/index.ts
2067
2329
  function transpile(source, filename, option) {
2068
2330
  const ast = parse(source);
2069
2331
  return transform(ast, option, {
@@ -2072,7 +2334,9 @@ function transpile(source, filename, option) {
2072
2334
  });
2073
2335
  }
2074
2336
  function transpileForVolar(source, filename, option) {
2075
- const ast = parseLoose(source);
2337
+ const ast = parseLoose(source, {
2338
+ recordCallLParens: true
2339
+ });
2076
2340
  return transformForVolar(ast, option, {
2077
2341
  content: source,
2078
2342
  filename
@@ -2081,5 +2345,8 @@ function transpileForVolar(source, filename, option) {
2081
2345
  export {
2082
2346
  transpileForVolar,
2083
2347
  transpile,
2348
+ resolveGtsConfigSync,
2349
+ resolveGtsConfig,
2350
+ path,
2084
2351
  GtsTranspilerError
2085
2352
  };