@gi-tcg/gts-transpiler 0.4.6 → 0.6.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.d.ts CHANGED
@@ -517,8 +517,6 @@ declare function parseLoose(input: string, options?: ParseLooseOptions): Program
517
517
  interface TranspileOption {
518
518
  runtimeImportSource?: string;
519
519
  providerImportSource?: string;
520
- shortcutFunctionPreludes?: string[];
521
- queryBindings?: string[];
522
520
  }
523
521
  //#endregion
524
522
  //#region ../../node_modules/@volar/source-map/lib/sourceMap.d.ts
package/dist/index.js CHANGED
@@ -61,8 +61,7 @@ const specialIdentifiers = [
61
61
  "of",
62
62
  "set",
63
63
  "type",
64
- "define",
65
- "query"
64
+ "define"
66
65
  ];
67
66
  function loosePlugin() {
68
67
  return function loosePluginTransformer(parser) {
@@ -238,21 +237,6 @@ function gtsPlugin(options = {}) {
238
237
  }
239
238
  return super.parseExprAtom(refDestructuringErrors, forInit, forNew);
240
239
  }
241
- parseMaybeUnary(refDestructuringErrors, sawUnary, incDec, forInit) {
242
- if (this.isShortcutContext && this.isContextual("query")) {
243
- const expr = this.gts_parseQueryExpression();
244
- if (!incDec && this.eat(tokTypes.starstar)) this.unexpected(this.lastTokStart);
245
- return expr;
246
- }
247
- return super.parseMaybeUnary(refDestructuringErrors, sawUnary, incDec, forInit);
248
- }
249
- gts_parseQueryExpression(forInit) {
250
- const node = this.startNode();
251
- this.next();
252
- if (this.eat(tokTypes.star)) node.star = true;
253
- node.argument = this.parseMaybeUnary(null, true, false, forInit);
254
- return this.finishNode(node, "GTSQueryExpression");
255
- }
256
240
  };
257
241
  };
258
242
  }
@@ -712,14 +696,6 @@ const eraseTs = (ast) => {
712
696
  return walk(ast, null, eraseTsVisitor);
713
697
  };
714
698
  //#endregion
715
- //#region src/transform/constants.ts
716
- const DEFAULT_SHORTCUT_FUNCTION_PRELUDES = ["$"];
717
- const DEFAULT_QUERY_BINDINGS = [
718
- "my",
719
- "opp",
720
- "macros"
721
- ];
722
- //#endregion
723
699
  //#region src/transform/gts.ts
724
700
  const commonGtsVisitor = {
725
701
  GTSDirectFunction(node, { visit, state }) {
@@ -757,7 +733,7 @@ const commonGtsVisitor = {
757
733
  type: "ArrayExpression",
758
734
  elements: [{
759
735
  type: "ArrowFunctionExpression",
760
- params: state.shortcutFunctionParameters,
736
+ params: [state.fnArgId],
761
737
  body: {
762
738
  type: "BlockStatement",
763
739
  body: node.body.map((stmt) => visit(stmt))
@@ -791,7 +767,7 @@ const commonGtsVisitor = {
791
767
  GTSShortcutFunctionExpression(node, { visit, state }) {
792
768
  return {
793
769
  type: "ArrowFunctionExpression",
794
- params: state.shortcutFunctionParameters,
770
+ params: [state.fnArgId],
795
771
  body: visit(node.body),
796
772
  expression: node.expression,
797
773
  loc: node.loc,
@@ -808,28 +784,6 @@ const commonGtsVisitor = {
808
784
  loc: node.loc,
809
785
  range: node.range
810
786
  };
811
- },
812
- GTSQueryExpression(node, { state, visit }) {
813
- return {
814
- ...node,
815
- type: "CallExpression",
816
- optional: false,
817
- callee: {
818
- type: "MemberExpression",
819
- object: state.fnArgId,
820
- property: node.star ? state.QueryAllLit : state.QueryLit,
821
- computed: true,
822
- optional: false
823
- },
824
- arguments: [{
825
- type: "ArrowFunctionExpression",
826
- body: visit(node.argument),
827
- params: state.queryParameters,
828
- expression: true,
829
- loc: node.argument.loc,
830
- range: node.argument.range
831
- }]
832
- };
833
787
  }
834
788
  };
835
789
  const gtsVisitor = {
@@ -1099,16 +1053,6 @@ const gtsVisitor = {
1099
1053
  ...commonGtsVisitor
1100
1054
  };
1101
1055
  const initialTranspileState = (option = {}) => {
1102
- const shortcutFunctionPreludes = option.shortcutFunctionPreludes ?? DEFAULT_SHORTCUT_FUNCTION_PRELUDES;
1103
- const queryBindings = option.queryBindings ?? DEFAULT_QUERY_BINDINGS;
1104
- const fnArgId = {
1105
- type: "Identifier",
1106
- name: "__gts_fnArg"
1107
- };
1108
- const PreludeLit = {
1109
- type: "Literal",
1110
- value: "~prelude"
1111
- };
1112
1056
  return {
1113
1057
  createDefineFnId: {
1114
1058
  type: "Identifier",
@@ -1122,66 +1066,14 @@ const initialTranspileState = (option = {}) => {
1122
1066
  type: "Literal",
1123
1067
  value: "~action"
1124
1068
  },
1125
- PreludeLit,
1126
- fnArgId,
1127
- shortcutFunctionParameters: [fnArgId, {
1128
- type: "AssignmentPattern",
1129
- left: {
1130
- type: "ObjectPattern",
1131
- properties: shortcutFunctionPreludes.map((name) => ({
1132
- type: "Property",
1133
- computed: false,
1134
- key: {
1135
- type: "Identifier",
1136
- name
1137
- },
1138
- value: {
1139
- type: "Identifier",
1140
- name
1141
- },
1142
- kind: "init",
1143
- method: false,
1144
- shorthand: true
1145
- }))
1146
- },
1147
- right: {
1148
- type: "MemberExpression",
1149
- object: fnArgId,
1150
- property: PreludeLit,
1151
- computed: true,
1152
- optional: false
1153
- }
1154
- }],
1069
+ fnArgId: {
1070
+ type: "Identifier",
1071
+ name: "__gts_fnArg"
1072
+ },
1155
1073
  rootVmId: {
1156
1074
  type: "Identifier",
1157
1075
  name: "__gts_rootVm"
1158
1076
  },
1159
- queryParameters: [{
1160
- type: "ObjectPattern",
1161
- properties: queryBindings.map((name) => ({
1162
- type: "Property",
1163
- computed: false,
1164
- key: {
1165
- type: "Identifier",
1166
- name
1167
- },
1168
- value: {
1169
- type: "Identifier",
1170
- name
1171
- },
1172
- kind: "init",
1173
- method: false,
1174
- shorthand: true
1175
- }))
1176
- }],
1177
- QueryLit: {
1178
- type: "Literal",
1179
- value: "~query"
1180
- },
1181
- QueryAllLit: {
1182
- type: "Literal",
1183
- value: "~queryAll"
1184
- },
1185
1077
  runtimeImportSource: option.runtimeImportSource ?? "@gi-tcg/gts-runtime",
1186
1078
  providerImportSource: option.providerImportSource ?? "@gi-tcg/core/gts",
1187
1079
  externalizedBindings: [],
@@ -1306,11 +1198,20 @@ function applyReplacements(state, code, mappings) {
1306
1198
  let ${payload.typingId} = ${typingIdLhs}.as();
1307
1199
  type ${payload.typingId} = typeof ${payload.typingId};
1308
1200
  `;
1309
- } else if (payload.type === "exitAttr") replacement = dedent`
1201
+ } else if (payload.type === "exitAttr") {
1202
+ const rewrittenMeta = `${payload.oldMetaType}_rewritten`;
1203
+ const mergeFn = `${payload.oldMetaType}_mergeFn`;
1204
+ const mergeFnRet = `${payload.oldMetaType}_mergeFnRet`;
1205
+ replacement = dedent`
1310
1206
  type ${payload.returnType} = typeof ${payload.returnType};
1311
- type ${payload.newMetaType} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType}
1207
+ type ${rewrittenMeta} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType};
1208
+ let ${mergeFn}!: ${payload.defType} extends {
1209
+ [${payload.attrName}]: { mergeMeta: infer M }
1210
+ } ? M : null;
1211
+ let ${mergeFnRet} = ${mergeFn}?.(null! as ${rewrittenMeta}, null! as ${payload.innerMetaType});
1212
+ type ${payload.newMetaType} = [typeof ${mergeFn}] extends [null] ? ${rewrittenMeta} : typeof ${mergeFnRet};
1312
1213
  `;
1313
- else replacement = "";
1214
+ } else replacement = "";
1314
1215
  matchInfos.push({
1315
1216
  sourceEnd: offset + match.length,
1316
1217
  lengthOffset: replacement.length - match.length
@@ -1390,6 +1291,7 @@ const exitVM = (state, errorRange) => {
1390
1291
  collectedAttrs: collectedAttrNames,
1391
1292
  errorRange
1392
1293
  }));
1294
+ return { finalMetaId };
1393
1295
  };
1394
1296
  const enterAttr = (state, attrName) => {
1395
1297
  const defTypeId = state.vmDefTypeIdStack.at(-1);
@@ -1425,7 +1327,7 @@ const genBindingTyping = (state, info) => {
1425
1327
  typingId: info.typingId.name
1426
1328
  }));
1427
1329
  };
1428
- const exitAttr = (state, returningId) => {
1330
+ const exitAttr = (state, attrName, innerVMFinalMetaId, returningId) => {
1429
1331
  const currentDefId = state.vmDefTypeIdStack.at(-1);
1430
1332
  if (!currentDefId) return;
1431
1333
  const newMetaTypeId = {
@@ -1436,6 +1338,8 @@ const exitAttr = (state, returningId) => {
1436
1338
  state.typingPendingStatements.push(createReplacementHolder(state, {
1437
1339
  type: "exitAttr",
1438
1340
  defType: currentDefId.name,
1341
+ attrName,
1342
+ innerMetaType: innerVMFinalMetaId.name,
1439
1343
  oldMetaType: oldMetaTypeId.name,
1440
1344
  newMetaType: newMetaTypeId.name,
1441
1345
  returnType: returningId.name
@@ -1616,10 +1520,11 @@ const gtsToTypingsWalker = {
1616
1520
  }]
1617
1521
  });
1618
1522
  enterVMFromAttr(state, returnValue);
1523
+ let exitVMResult;
1619
1524
  if (body.namedAttributes) {
1620
1525
  visit(body.namedAttributes);
1621
- exitVM(state, body.namedAttributes.range);
1622
- } else exitVM(state, name.range);
1526
+ exitVMResult = exitVM(state, body.namedAttributes.range);
1527
+ } else exitVMResult = exitVM(state, name.range);
1623
1528
  if (bindingName) {
1624
1529
  const export_ = node.bindingAccessModifier !== "private";
1625
1530
  const typingId = {
@@ -1646,7 +1551,7 @@ const gtsToTypingsWalker = {
1646
1551
  leadingComments: state.defineLeadingComments
1647
1552
  });
1648
1553
  }
1649
- exitAttr(state, returnValue);
1554
+ exitAttr(state, attrName, exitVMResult.finalMetaId, returnValue);
1650
1555
  return EMPTY;
1651
1556
  },
1652
1557
  GTSNamedAttributeBlock(node, { state, visit }) {
@@ -1686,7 +1591,7 @@ const gtsToTypingsWalker = {
1686
1591
  }
1687
1592
  const fn = {
1688
1593
  type: "ArrowFunctionExpression",
1689
- params: state.shortcutFunctionParameters,
1594
+ params: [state.fnArgId],
1690
1595
  body: {
1691
1596
  type: "BlockStatement",
1692
1597
  body: node.directAction.body.map((stmt) => visit(stmt))
@@ -1761,6 +1666,14 @@ function getPrintOptions(source, state) {
1761
1666
  getLeadingComments: (node) => node.leadingComments,
1762
1667
  getTrailingComments: (node) => node.trailingComments,
1763
1668
  getMappingData: () => DEFAULT_VOLAR_MAPPING_DATA,
1669
+ beforeWriteNode: ({ range, isUntouched, context }) => {
1670
+ if (isUntouched || !range) return;
1671
+ context.writeMapped("", range.start, range.start, VERIFICATION_ONLY_MAPPING_DATA);
1672
+ },
1673
+ afterWriteNode: ({ range, isUntouched, context }) => {
1674
+ if (isUntouched || !range) return;
1675
+ context.writeMapped("", range.end, range.end, VERIFICATION_ONLY_MAPPING_DATA);
1676
+ },
1764
1677
  printers: {
1765
1678
  Identifier(node, context) {
1766
1679
  const identifier = node;
@@ -1780,11 +1693,6 @@ function getPrintOptions(source, state) {
1780
1693
  context.write("\"");
1781
1694
  context.writeMapped(text.slice(1, -1), node.range[0], node.range[1], LITERAL_FROM_ID_MAPPING_DATA);
1782
1695
  context.write("\"");
1783
- const generatedEnd = context.generatedOffset;
1784
- context.createExtraMapping({
1785
- start: node.range[0],
1786
- end: node.range[1]
1787
- }, generatedStart, generatedEnd, VERIFICATION_ONLY_MAPPING_DATA);
1788
1696
  } else if (state.attributeNameNodes.has(node) && node.range) context.writeMapped(node.raw ?? JSON.stringify(node.value), node.range[0], node.range[1], ATTRIBUTE_NAME_MAPPING_DATA);
1789
1697
  else if (directActionStubRange = state.directActionStubRange.get(node)) context.writeMapped(node.raw ?? JSON.stringify(node.value), directActionStubRange.start, directActionStubRange.start + 1, DIRECT_ACTION_STUB_MAPPING_DATA);
1790
1698
  else defaultPrinters.Literal(node, context);
@@ -1998,13 +1906,7 @@ function transform(ast, option = {}, sourceInfo = {}) {
1998
1906
  //#region src/config.ts
1999
1907
  const DEFAULT_GTS_CONFIG = {
2000
1908
  runtimeImportSource: "@gi-tcg/gts-runtime",
2001
- providerImportSource: "@gi-tcg/core/gts",
2002
- shortcutFunctionPreludes: ["$"],
2003
- queryBindings: [
2004
- "my",
2005
- "opp",
2006
- "macros"
2007
- ]
1909
+ providerImportSource: "@gi-tcg/core/gts"
2008
1910
  };
2009
1911
  function* resolveGtsConfigImpl(filePath, inlineConfig = {}, options) {
2010
1912
  const pathModule = options.pathModule || browserPath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gi-tcg/gts-transpiler",
3
- "version": "0.4.6",
3
+ "version": "0.6.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/piovium/gts.git"
@@ -22,7 +22,7 @@
22
22
  "@sveltejs/acorn-typescript": "^1.0.8",
23
23
  "acorn": "^8.15.0",
24
24
  "dedent": "^1.7.2",
25
- "espolar": "^0.6.1",
25
+ "espolar": "^0.6.3",
26
26
  "esrap": "2.2.1",
27
27
  "magic-string": "^0.30.21",
28
28
  "path-browserify-esm": "^1.0.6",
package/src/config.ts CHANGED
@@ -33,8 +33,6 @@ export interface ResolveGtsConfigAsyncOptions extends ResolveGtsConfigBaseOption
33
33
  const DEFAULT_GTS_CONFIG: Required<GtsConfig> = {
34
34
  runtimeImportSource: "@gi-tcg/gts-runtime",
35
35
  providerImportSource: "@gi-tcg/core/gts",
36
- shortcutFunctionPreludes: ["$"],
37
- queryBindings: ["my", "opp", "macros"],
38
36
  };
39
37
 
40
38
  function* resolveGtsConfigImpl(
package/src/keywords.ts CHANGED
@@ -59,5 +59,4 @@ export const specialIdentifiers: string[] = [
59
59
  "type",
60
60
  // Our DSL Keywords
61
61
  "define",
62
- "query",
63
62
  ];
@@ -65,8 +65,6 @@ PrimaryExpression:
65
65
  ShortcutArgumentExpression:
66
66
  ":" Identifier
67
67
 
68
- UnaryExpression:
69
- + query UnaryExpression
70
68
  */
71
69
 
72
70
  export interface GtsPluginOption {
@@ -318,38 +316,6 @@ export function gtsPlugin(options: GtsPluginOption = {}) {
318
316
  return super.parseExprAtom(refDestructuringErrors, forInit, forNew);
319
317
  }
320
318
 
321
- override parseMaybeUnary(
322
- refDestructuringErrors?: Parse.DestructuringErrors | null,
323
- sawUnary?: boolean,
324
- incDec?: boolean,
325
- forInit?: boolean | "await",
326
- ): AST.Expression {
327
- if (this.isShortcutContext && this.isContextual("query")) {
328
- const expr = this.gts_parseQueryExpression();
329
- if (!incDec && this.eat(tokTypes.starstar)) {
330
- this.unexpected(this.lastTokStart);
331
- }
332
- return expr;
333
- }
334
- return super.parseMaybeUnary(
335
- refDestructuringErrors,
336
- sawUnary,
337
- incDec,
338
- forInit,
339
- );
340
- }
341
-
342
- gts_parseQueryExpression(
343
- forInit?: boolean | "await",
344
- ): AST.GTSQueryExpression {
345
- const node = this.startNode() as AST.GTSQueryExpression;
346
- this.next(); // consume 'query'
347
- if (this.eat(tokTypes.star)) {
348
- node.star = true;
349
- }
350
- node.argument = this.parseMaybeUnary(null, true, false, forInit);
351
- return this.finishNode(node, "GTSQueryExpression");
352
- }
353
319
  };
354
320
  };
355
321
  }
@@ -16,11 +16,6 @@ import type {
16
16
  } from "estree";
17
17
  import { walk, type Visitors } from "zimmerframe";
18
18
  import { GtsTranspilerError } from "../error.ts";
19
- import {
20
- DEFAULT_QUERY_BINDINGS,
21
- DEFAULT_SHORTCUT_FUNCTION_PRELUDES,
22
- } from "./constants.ts";
23
-
24
19
  export interface ExternalizedBinding {
25
20
  bindingName: Identifier;
26
21
  export: boolean;
@@ -30,13 +25,8 @@ export interface TranspileState {
30
25
  readonly createDefineFnId: Identifier;
31
26
  readonly createBindingFnId: Identifier;
32
27
  readonly ActionLit: Literal;
33
- readonly PreludeLit: Literal;
34
28
  readonly fnArgId: Identifier;
35
- readonly shortcutFunctionParameters: Pattern[];
36
29
  readonly rootVmId: Identifier;
37
- readonly queryParameters: Pattern[];
38
- readonly QueryLit: Literal;
39
- readonly QueryAllLit: Literal;
40
30
 
41
31
  readonly runtimeImportSource: string;
42
32
  readonly providerImportSource: string;
@@ -80,7 +70,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
80
70
  elements: [
81
71
  {
82
72
  type: "ArrowFunctionExpression",
83
- params: state.shortcutFunctionParameters,
73
+ params: [state.fnArgId],
84
74
  body: {
85
75
  type: "BlockStatement",
86
76
  body: node.body.map((stmt) => visit(stmt) as Statement),
@@ -115,7 +105,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
115
105
  ): ArrowFunctionExpression {
116
106
  return {
117
107
  type: "ArrowFunctionExpression",
118
- params: state.shortcutFunctionParameters,
108
+ params: [state.fnArgId],
119
109
  body: visit(node.body) as Expression | BlockStatement,
120
110
  expression: node.expression,
121
111
  loc: node.loc,
@@ -133,30 +123,6 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
133
123
  range: node.range,
134
124
  };
135
125
  },
136
- GTSQueryExpression(node, { state, visit }) {
137
- return {
138
- ...node,
139
- type: "CallExpression",
140
- optional: false,
141
- callee: {
142
- type: "MemberExpression",
143
- object: state.fnArgId,
144
- property: node.star ? state.QueryAllLit : state.QueryLit,
145
- computed: true,
146
- optional: false,
147
- },
148
- arguments: [
149
- {
150
- type: "ArrowFunctionExpression",
151
- body: visit(node.argument) as Expression,
152
- params: state.queryParameters,
153
- expression: true,
154
- loc: node.argument.loc,
155
- range: node.argument.range,
156
- },
157
- ],
158
- };
159
- },
160
126
  };
161
127
 
162
128
  const gtsVisitor: Visitors<Node, TranspileState> = {
@@ -446,71 +412,18 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
446
412
  export interface TranspileOption {
447
413
  runtimeImportSource?: string;
448
414
  providerImportSource?: string;
449
- shortcutFunctionPreludes?: string[];
450
- queryBindings?: string[];
451
415
  }
452
416
 
453
417
  export const initialTranspileState = (
454
418
  option: TranspileOption = {}
455
419
  ): TranspileState => {
456
- const shortcutFunctionPreludes =
457
- option.shortcutFunctionPreludes ?? DEFAULT_SHORTCUT_FUNCTION_PRELUDES;
458
- const queryBindings = option.queryBindings ?? DEFAULT_QUERY_BINDINGS;
459
420
  const fnArgId: Identifier = { type: "Identifier", name: "__gts_fnArg" };
460
- const PreludeLit: Literal = {
461
- type: "Literal",
462
- value: "~prelude",
463
- };
464
- const shortcutFunctionParameters: Pattern[] = [
465
- fnArgId,
466
- {
467
- type: "AssignmentPattern",
468
- left: {
469
- type: "ObjectPattern",
470
- properties: shortcutFunctionPreludes.map((name) => ({
471
- type: "Property",
472
- computed: false,
473
- key: { type: "Identifier", name },
474
- value: { type: "Identifier", name },
475
- kind: "init",
476
- method: false,
477
- shorthand: true,
478
- })),
479
- },
480
- right: {
481
- type: "MemberExpression",
482
- object: fnArgId,
483
- property: PreludeLit,
484
- computed: true,
485
- optional: false,
486
- },
487
- },
488
- ];
489
- const queryParameters: Pattern[] = [
490
- {
491
- type: "ObjectPattern",
492
- properties: queryBindings.map((name) => ({
493
- type: "Property",
494
- computed: false,
495
- key: { type: "Identifier", name },
496
- value: { type: "Identifier", name },
497
- kind: "init",
498
- method: false,
499
- shorthand: true,
500
- })),
501
- },
502
- ];
503
421
  return {
504
422
  createDefineFnId: { type: "Identifier", name: "__gts_createDefine" },
505
423
  createBindingFnId: { type: "Identifier", name: "__gts_createBinding" },
506
424
  ActionLit: { type: "Literal", value: "~action" },
507
- PreludeLit,
508
425
  fnArgId,
509
- shortcutFunctionParameters,
510
426
  rootVmId: { type: "Identifier", name: "__gts_rootVm" },
511
- queryParameters,
512
- QueryLit: { type: "Literal", value: "~query" },
513
- QueryAllLit: { type: "Literal", value: "~queryAll" },
514
427
 
515
428
  runtimeImportSource: option.runtimeImportSource ?? "@gi-tcg/gts-runtime",
516
429
  providerImportSource: option.providerImportSource ?? "@gi-tcg/core/gts",
@@ -41,6 +41,20 @@ export function getPrintOptions(
41
41
  getLeadingComments: (node) => (node as Node).leadingComments,
42
42
  getTrailingComments: (node) => (node as Node).trailingComments,
43
43
  getMappingData: () => DEFAULT_VOLAR_MAPPING_DATA,
44
+ // Add a 0-length mapping before and after each touched node with verification only,
45
+ // so that error squiggles start/ends at those positions can be reflected.
46
+ beforeWriteNode: ({ range, isUntouched, context }) => {
47
+ if (isUntouched || !range) {
48
+ return;
49
+ }
50
+ context.writeMapped("", range.start, range.start, VERIFICATION_ONLY_MAPPING_DATA);
51
+ },
52
+ afterWriteNode: ({ range, isUntouched, context }) => {
53
+ if (isUntouched || !range) {
54
+ return;
55
+ }
56
+ context.writeMapped("", range.end, range.end, VERIFICATION_ONLY_MAPPING_DATA);
57
+ },
44
58
  printers: {
45
59
  // 1) Make the print of dummy identifier print nothing.
46
60
  // Exception: if GTS attribute list's last argument is dummy, e.g.
@@ -94,17 +108,6 @@ export function getPrintOptions(
94
108
  LITERAL_FROM_ID_MAPPING_DATA,
95
109
  );
96
110
  context.write('"');
97
- const generatedEnd = context.generatedOffset;
98
- // Map error squiggle at quotation mark to the inner content
99
- context.createExtraMapping(
100
- {
101
- start: node.range[0],
102
- end: node.range[1],
103
- },
104
- generatedStart,
105
- generatedEnd,
106
- VERIFICATION_ONLY_MAPPING_DATA,
107
- )
108
111
  } else if (state.attributeNameNodes.has(node) && node.range) {
109
112
  context.writeMapped(
110
113
  node.raw ?? JSON.stringify((node as EspolarAST.Literal).value),
@@ -51,6 +51,8 @@ type ReplacementPayload =
51
51
  type: "exitAttr";
52
52
  returnType: string;
53
53
  defType: string;
54
+ attrName: string;
55
+ innerMetaType: string;
54
56
  oldMetaType: string;
55
57
  newMetaType: string;
56
58
  };
@@ -194,9 +196,17 @@ export function applyReplacements(
194
196
  type ${payload.typingId} = typeof ${payload.typingId};
195
197
  `;
196
198
  } else if (payload.type === "exitAttr") {
199
+ const rewrittenMeta = `${payload.oldMetaType}_rewritten`;
200
+ const mergeFn = `${payload.oldMetaType}_mergeFn`;
201
+ const mergeFnRet = `${payload.oldMetaType}_mergeFnRet`;
197
202
  replacement = dedent`
198
203
  type ${payload.returnType} = typeof ${payload.returnType};
199
- type ${payload.newMetaType} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType}
204
+ type ${rewrittenMeta} = ${payload.returnType} extends { rewriteMeta: infer NewMeta extends {} } ? NewMeta : ${payload.oldMetaType};
205
+ let ${mergeFn}!: ${payload.defType} extends {
206
+ [${payload.attrName}]: { mergeMeta: infer M }
207
+ } ? M : null;
208
+ let ${mergeFnRet} = ${mergeFn}?.(null! as ${rewrittenMeta}, null! as ${payload.innerMetaType});
209
+ type ${payload.newMetaType} = [typeof ${mergeFn}] extends [null] ? ${rewrittenMeta} : typeof ${mergeFnRet};
200
210
  `;
201
211
  } else {
202
212
  replacement = "";
@@ -168,7 +168,14 @@ const enterVMFromAttr = (
168
168
  state.attrsOfCurrentVm.push([]);
169
169
  };
170
170
 
171
- const exitVM = (state: TypingTranspileState, errorRange?: [number, number]) => {
171
+ interface ExitVMResult {
172
+ finalMetaId: Identifier;
173
+ }
174
+
175
+ const exitVM = (
176
+ state: TypingTranspileState,
177
+ errorRange?: [number, number],
178
+ ): ExitVMResult => {
172
179
  const currentDefTypeId = state.vmDefTypeIdStack.pop()!;
173
180
  const currentMetaId = state.metaTypeIdStack.pop()!;
174
181
  const finalMetaId = state.finalMetaTypeIdStack.pop()!;
@@ -183,17 +190,24 @@ const exitVM = (state: TypingTranspileState, errorRange?: [number, number]) => {
183
190
  errorRange,
184
191
  }),
185
192
  );
193
+ return { finalMetaId };
186
194
  };
187
195
 
196
+ interface EnterAttrResult {
197
+ lhsId: Identifier;
198
+ }
199
+
188
200
  const enterAttr = (
189
201
  state: TypingTranspileState,
190
202
  attrName: string,
191
- ): { lhsId: Identifier } => {
203
+ ): EnterAttrResult => {
192
204
  const defTypeId = state.vmDefTypeIdStack.at(-1);
193
205
  const metaTypeId = state.metaTypeIdStack.at(-1);
194
206
  if (!defTypeId || !metaTypeId) {
195
207
  // FIXME error handling?
196
- return { lhsId: { type: "Identifier", name: "__gts_invalid_attr_obj" } };
208
+ return {
209
+ lhsId: { type: "Identifier", name: "__gts_invalid_attr_obj" },
210
+ };
197
211
  }
198
212
  state.attrsOfCurrentVm.at(-1)!.push(attrName);
199
213
  const lhsId: Identifier = {
@@ -210,7 +224,7 @@ const enterAttr = (
210
224
  hintOnly: attrName === ATTR_HINT_ATTR_NAME,
211
225
  }),
212
226
  );
213
- return { lhsId: lhsId };
227
+ return { lhsId };
214
228
  };
215
229
 
216
230
  const genBindingTyping = (
@@ -236,7 +250,12 @@ const genBindingTyping = (
236
250
  );
237
251
  };
238
252
 
239
- const exitAttr = (state: TypingTranspileState, returningId: Identifier) => {
253
+ const exitAttr = (
254
+ state: TypingTranspileState,
255
+ attrName: string,
256
+ innerVMFinalMetaId: Identifier,
257
+ returningId: Identifier,
258
+ ) => {
240
259
  const currentDefId = state.vmDefTypeIdStack.at(-1);
241
260
  if (!currentDefId) {
242
261
  return;
@@ -250,6 +269,8 @@ const exitAttr = (state: TypingTranspileState, returningId: Identifier) => {
250
269
  createReplacementHolder(state, {
251
270
  type: "exitAttr",
252
271
  defType: currentDefId.name,
272
+ attrName,
273
+ innerMetaType: innerVMFinalMetaId.name,
253
274
  oldMetaType: oldMetaTypeId.name,
254
275
  newMetaType: newMetaTypeId.name,
255
276
  returnType: returningId.name,
@@ -473,11 +494,12 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
473
494
  ],
474
495
  });
475
496
  enterVMFromAttr(state, returnValue);
497
+ let exitVMResult: ExitVMResult;
476
498
  if (body.namedAttributes) {
477
499
  visit(body.namedAttributes);
478
- exitVM(state, body.namedAttributes.range);
500
+ exitVMResult = exitVM(state, body.namedAttributes.range);
479
501
  } else {
480
- exitVM(state, name.range);
502
+ exitVMResult = exitVM(state, name.range);
481
503
  }
482
504
  if (bindingName) {
483
505
  const export_ = node.bindingAccessModifier !== "private";
@@ -505,7 +527,7 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
505
527
  leadingComments: state.defineLeadingComments,
506
528
  });
507
529
  }
508
- exitAttr(state, returnValue);
530
+ exitAttr(state, attrName, exitVMResult.finalMetaId, returnValue);
509
531
  return EMPTY;
510
532
  },
511
533
  GTSNamedAttributeBlock(node, { state, visit }) {
@@ -561,7 +583,7 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
561
583
  }
562
584
  const fn: ArrowFunctionExpression = {
563
585
  type: "ArrowFunctionExpression",
564
- params: state.shortcutFunctionParameters,
586
+ params: [state.fnArgId],
565
587
  body: {
566
588
  type: "BlockStatement",
567
589
  body: node.directAction.body.map((stmt) => visit(stmt) as Statement),
package/src/types.ts CHANGED
@@ -21,7 +21,6 @@ declare module "estree" {
21
21
  interface ExpressionMap {
22
22
  GTSShortcutArgumentExpression: GTSShortcutArgumentExpression;
23
23
  GTSShortcutFunctionExpression: GTSShortcutFunctionExpression;
24
- GTSQueryExpression: GTSQueryExpression;
25
24
  }
26
25
 
27
26
  interface SimpleCallExpression {
@@ -77,11 +76,6 @@ declare module "estree" {
77
76
  expression: boolean;
78
77
  }
79
78
 
80
- interface GTSQueryExpression extends BaseExpression {
81
- type: "GTSQueryExpression";
82
- star?: boolean;
83
- argument: Expression;
84
- }
85
79
  }
86
80
 
87
81
  declare module "acorn" {
@@ -1,2 +0,0 @@
1
- export const DEFAULT_SHORTCUT_FUNCTION_PRELUDES: string[] = ["$"];
2
- export const DEFAULT_QUERY_BINDINGS: string[] = ["my", "opp", "macros"];