@gi-tcg/gts-transpiler 0.3.7 → 0.3.9

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
@@ -1,6 +1,40 @@
1
+ import { Options, Parser } from "acorn";
1
2
  import { SourceMap } from "magic-string";
2
3
 
3
4
  //#region node_modules/@types/estree/index.d.ts
5
+ // This definition file follows a somewhat unusual format. ESTree allows
6
+ // runtime type checks based on the `type` parameter. In order to explain this
7
+ // to typescript we want to use discriminated union types:
8
+ // https://github.com/Microsoft/TypeScript/pull/9163
9
+ //
10
+ // For ESTree this is a bit tricky because the high level interfaces like
11
+ // Node or Function are pulling double duty. We want to pass common fields down
12
+ // to the interfaces that extend them (like Identifier or
13
+ // ArrowFunctionExpression), but you can't extend a type union or enforce
14
+ // common fields on them. So we've split the high level interfaces into two
15
+ // types, a base type which passes down inherited fields, and a type union of
16
+ // all types which extend the base type. Only the type union is exported, and
17
+ // the union is how other types refer to the collection of inheriting types.
18
+ //
19
+ // This makes the definitions file here somewhat more difficult to maintain,
20
+ // but it has the notable advantage of making ESTree much easier to use as
21
+ // an end user.
22
+ interface BaseNodeWithoutComments {
23
+ // Every leaf interface that extends BaseNode must specify a type property.
24
+ // The type property should be a string literal. For example, Identifier
25
+ // has: `type: "Identifier"`
26
+ type: string;
27
+ loc?: SourceLocation | null | undefined;
28
+ range?: [number, number] | undefined;
29
+ }
30
+ interface BaseNode extends BaseNodeWithoutComments {
31
+ leadingComments?: Comment[] | undefined;
32
+ trailingComments?: Comment[] | undefined;
33
+ }
34
+ interface Comment extends BaseNodeWithoutComments {
35
+ type: "Line" | "Block";
36
+ value: string;
37
+ }
4
38
  interface SourceLocation {
5
39
  source?: string | null | undefined;
6
40
  start: Position;
@@ -12,6 +46,472 @@ interface Position {
12
46
  /** >= 0 */
13
47
  column: number;
14
48
  }
49
+ interface Program extends BaseNode {
50
+ type: "Program";
51
+ sourceType: "script" | "module";
52
+ body: Array<Directive | Statement | ModuleDeclaration>;
53
+ comments?: Comment[] | undefined;
54
+ }
55
+ interface Directive extends BaseNode {
56
+ type: "ExpressionStatement";
57
+ expression: Literal;
58
+ directive: string;
59
+ }
60
+ interface BaseFunction extends BaseNode {
61
+ params: Pattern[];
62
+ generator?: boolean | undefined;
63
+ async?: boolean | undefined; // The body is either BlockStatement or Expression because arrow functions
64
+ // can have a body that's either. FunctionDeclarations and
65
+ // FunctionExpressions have only BlockStatement bodies.
66
+ body: BlockStatement | Expression;
67
+ }
68
+ type Statement = ExpressionStatement | BlockStatement | StaticBlock | EmptyStatement | DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement | BreakStatement | ContinueStatement | IfStatement | SwitchStatement | ThrowStatement | TryStatement | WhileStatement | DoWhileStatement | ForStatement | ForInStatement | ForOfStatement | Declaration;
69
+ interface BaseStatement extends BaseNode {}
70
+ interface EmptyStatement extends BaseStatement {
71
+ type: "EmptyStatement";
72
+ }
73
+ interface BlockStatement extends BaseStatement {
74
+ type: "BlockStatement";
75
+ body: Statement[];
76
+ innerComments?: Comment[] | undefined;
77
+ }
78
+ interface StaticBlock extends Omit<BlockStatement, "type"> {
79
+ type: "StaticBlock";
80
+ }
81
+ interface ExpressionStatement extends BaseStatement {
82
+ type: "ExpressionStatement";
83
+ expression: Expression;
84
+ }
85
+ interface IfStatement extends BaseStatement {
86
+ type: "IfStatement";
87
+ test: Expression;
88
+ consequent: Statement;
89
+ alternate?: Statement | null | undefined;
90
+ }
91
+ interface LabeledStatement extends BaseStatement {
92
+ type: "LabeledStatement";
93
+ label: Identifier;
94
+ body: Statement;
95
+ }
96
+ interface BreakStatement extends BaseStatement {
97
+ type: "BreakStatement";
98
+ label?: Identifier | null | undefined;
99
+ }
100
+ interface ContinueStatement extends BaseStatement {
101
+ type: "ContinueStatement";
102
+ label?: Identifier | null | undefined;
103
+ }
104
+ interface WithStatement extends BaseStatement {
105
+ type: "WithStatement";
106
+ object: Expression;
107
+ body: Statement;
108
+ }
109
+ interface SwitchStatement extends BaseStatement {
110
+ type: "SwitchStatement";
111
+ discriminant: Expression;
112
+ cases: SwitchCase[];
113
+ }
114
+ interface ReturnStatement extends BaseStatement {
115
+ type: "ReturnStatement";
116
+ argument?: Expression | null | undefined;
117
+ }
118
+ interface ThrowStatement extends BaseStatement {
119
+ type: "ThrowStatement";
120
+ argument: Expression;
121
+ }
122
+ interface TryStatement extends BaseStatement {
123
+ type: "TryStatement";
124
+ block: BlockStatement;
125
+ handler?: CatchClause | null | undefined;
126
+ finalizer?: BlockStatement | null | undefined;
127
+ }
128
+ interface WhileStatement extends BaseStatement {
129
+ type: "WhileStatement";
130
+ test: Expression;
131
+ body: Statement;
132
+ }
133
+ interface DoWhileStatement extends BaseStatement {
134
+ type: "DoWhileStatement";
135
+ body: Statement;
136
+ test: Expression;
137
+ }
138
+ interface ForStatement extends BaseStatement {
139
+ type: "ForStatement";
140
+ init?: VariableDeclaration | Expression | null | undefined;
141
+ test?: Expression | null | undefined;
142
+ update?: Expression | null | undefined;
143
+ body: Statement;
144
+ }
145
+ interface BaseForXStatement extends BaseStatement {
146
+ left: VariableDeclaration | Pattern;
147
+ right: Expression;
148
+ body: Statement;
149
+ }
150
+ interface ForInStatement extends BaseForXStatement {
151
+ type: "ForInStatement";
152
+ }
153
+ interface DebuggerStatement extends BaseStatement {
154
+ type: "DebuggerStatement";
155
+ }
156
+ type Declaration = FunctionDeclaration | VariableDeclaration | ClassDeclaration;
157
+ interface BaseDeclaration extends BaseStatement {}
158
+ interface MaybeNamedFunctionDeclaration extends BaseFunction, BaseDeclaration {
159
+ type: "FunctionDeclaration";
160
+ /** It is null when a function declaration is a part of the `export default function` statement */
161
+ id: Identifier | null;
162
+ body: BlockStatement;
163
+ }
164
+ interface FunctionDeclaration extends MaybeNamedFunctionDeclaration {
165
+ id: Identifier;
166
+ }
167
+ interface VariableDeclaration extends BaseDeclaration {
168
+ type: "VariableDeclaration";
169
+ declarations: VariableDeclarator[];
170
+ kind: "var" | "let" | "const" | "using" | "await using";
171
+ }
172
+ interface VariableDeclarator extends BaseNode {
173
+ type: "VariableDeclarator";
174
+ id: Pattern;
175
+ init?: Expression | null | undefined;
176
+ }
177
+ interface ExpressionMap {
178
+ ArrayExpression: ArrayExpression;
179
+ ArrowFunctionExpression: ArrowFunctionExpression;
180
+ AssignmentExpression: AssignmentExpression;
181
+ AwaitExpression: AwaitExpression;
182
+ BinaryExpression: BinaryExpression;
183
+ CallExpression: CallExpression;
184
+ ChainExpression: ChainExpression;
185
+ ClassExpression: ClassExpression;
186
+ ConditionalExpression: ConditionalExpression;
187
+ FunctionExpression: FunctionExpression;
188
+ Identifier: Identifier;
189
+ ImportExpression: ImportExpression;
190
+ Literal: Literal;
191
+ LogicalExpression: LogicalExpression;
192
+ MemberExpression: MemberExpression;
193
+ MetaProperty: MetaProperty;
194
+ NewExpression: NewExpression;
195
+ ObjectExpression: ObjectExpression;
196
+ SequenceExpression: SequenceExpression;
197
+ TaggedTemplateExpression: TaggedTemplateExpression;
198
+ TemplateLiteral: TemplateLiteral;
199
+ ThisExpression: ThisExpression;
200
+ UnaryExpression: UnaryExpression;
201
+ UpdateExpression: UpdateExpression;
202
+ YieldExpression: YieldExpression;
203
+ }
204
+ type Expression = ExpressionMap[keyof ExpressionMap];
205
+ interface BaseExpression extends BaseNode {}
206
+ type ChainElement = SimpleCallExpression | MemberExpression;
207
+ interface ChainExpression extends BaseExpression {
208
+ type: "ChainExpression";
209
+ expression: ChainElement;
210
+ }
211
+ interface ThisExpression extends BaseExpression {
212
+ type: "ThisExpression";
213
+ }
214
+ interface ArrayExpression extends BaseExpression {
215
+ type: "ArrayExpression";
216
+ elements: Array<Expression | SpreadElement | null>;
217
+ }
218
+ interface ObjectExpression extends BaseExpression {
219
+ type: "ObjectExpression";
220
+ properties: Array<Property | SpreadElement>;
221
+ }
222
+ interface PrivateIdentifier extends BaseNode {
223
+ type: "PrivateIdentifier";
224
+ name: string;
225
+ }
226
+ interface Property extends BaseNode {
227
+ type: "Property";
228
+ key: Expression;
229
+ value: Expression | Pattern; // Could be an AssignmentProperty
230
+ kind: "init" | "get" | "set";
231
+ method: boolean;
232
+ shorthand: boolean;
233
+ computed: boolean;
234
+ }
235
+ interface PropertyDefinition extends BaseNode {
236
+ type: "PropertyDefinition";
237
+ key: Expression | PrivateIdentifier;
238
+ value?: Expression | null | undefined;
239
+ computed: boolean;
240
+ static: boolean;
241
+ }
242
+ interface FunctionExpression extends BaseFunction, BaseExpression {
243
+ id?: Identifier | null | undefined;
244
+ type: "FunctionExpression";
245
+ body: BlockStatement;
246
+ }
247
+ interface SequenceExpression extends BaseExpression {
248
+ type: "SequenceExpression";
249
+ expressions: Expression[];
250
+ }
251
+ interface UnaryExpression extends BaseExpression {
252
+ type: "UnaryExpression";
253
+ operator: UnaryOperator;
254
+ prefix: true;
255
+ argument: Expression;
256
+ }
257
+ interface BinaryExpression extends BaseExpression {
258
+ type: "BinaryExpression";
259
+ operator: BinaryOperator;
260
+ left: Expression | PrivateIdentifier;
261
+ right: Expression;
262
+ }
263
+ interface AssignmentExpression extends BaseExpression {
264
+ type: "AssignmentExpression";
265
+ operator: AssignmentOperator;
266
+ left: Pattern | MemberExpression;
267
+ right: Expression;
268
+ }
269
+ interface UpdateExpression extends BaseExpression {
270
+ type: "UpdateExpression";
271
+ operator: UpdateOperator;
272
+ argument: Expression;
273
+ prefix: boolean;
274
+ }
275
+ interface LogicalExpression extends BaseExpression {
276
+ type: "LogicalExpression";
277
+ operator: LogicalOperator;
278
+ left: Expression;
279
+ right: Expression;
280
+ }
281
+ interface ConditionalExpression extends BaseExpression {
282
+ type: "ConditionalExpression";
283
+ test: Expression;
284
+ alternate: Expression;
285
+ consequent: Expression;
286
+ }
287
+ interface BaseCallExpression extends BaseExpression {
288
+ callee: Expression | Super;
289
+ arguments: Array<Expression | SpreadElement>;
290
+ }
291
+ type CallExpression = SimpleCallExpression | NewExpression;
292
+ interface SimpleCallExpression extends BaseCallExpression {
293
+ type: "CallExpression";
294
+ optional: boolean;
295
+ }
296
+ interface NewExpression extends BaseCallExpression {
297
+ type: "NewExpression";
298
+ }
299
+ interface MemberExpression extends BaseExpression, BasePattern {
300
+ type: "MemberExpression";
301
+ object: Expression | Super;
302
+ property: Expression | PrivateIdentifier;
303
+ computed: boolean;
304
+ optional: boolean;
305
+ }
306
+ type Pattern = Identifier | ObjectPattern | ArrayPattern | RestElement | AssignmentPattern | MemberExpression;
307
+ interface BasePattern extends BaseNode {}
308
+ interface SwitchCase extends BaseNode {
309
+ type: "SwitchCase";
310
+ test?: Expression | null | undefined;
311
+ consequent: Statement[];
312
+ }
313
+ interface CatchClause extends BaseNode {
314
+ type: "CatchClause";
315
+ param: Pattern | null;
316
+ body: BlockStatement;
317
+ }
318
+ interface Identifier extends BaseNode, BaseExpression, BasePattern {
319
+ type: "Identifier";
320
+ name: string;
321
+ }
322
+ type Literal = SimpleLiteral | RegExpLiteral | BigIntLiteral;
323
+ interface SimpleLiteral extends BaseNode, BaseExpression {
324
+ type: "Literal";
325
+ value: string | boolean | number | null;
326
+ raw?: string | undefined;
327
+ }
328
+ interface RegExpLiteral extends BaseNode, BaseExpression {
329
+ type: "Literal";
330
+ value?: RegExp | null | undefined;
331
+ regex: {
332
+ pattern: string;
333
+ flags: string;
334
+ };
335
+ raw?: string | undefined;
336
+ }
337
+ interface BigIntLiteral extends BaseNode, BaseExpression {
338
+ type: "Literal";
339
+ value?: bigint | null | undefined;
340
+ bigint: string;
341
+ raw?: string | undefined;
342
+ }
343
+ type UnaryOperator = "-" | "+" | "!" | "~" | "typeof" | "void" | "delete";
344
+ type BinaryOperator = "==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" | ">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" | "instanceof";
345
+ type LogicalOperator = "||" | "&&" | "??";
346
+ type AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" | "|=" | "^=" | "&=" | "||=" | "&&=" | "??=";
347
+ type UpdateOperator = "++" | "--";
348
+ interface ForOfStatement extends BaseForXStatement {
349
+ type: "ForOfStatement";
350
+ await: boolean;
351
+ }
352
+ interface Super extends BaseNode {
353
+ type: "Super";
354
+ }
355
+ interface SpreadElement extends BaseNode {
356
+ type: "SpreadElement";
357
+ argument: Expression;
358
+ }
359
+ interface ArrowFunctionExpression extends BaseExpression, BaseFunction {
360
+ type: "ArrowFunctionExpression";
361
+ expression: boolean;
362
+ body: BlockStatement | Expression;
363
+ }
364
+ interface YieldExpression extends BaseExpression {
365
+ type: "YieldExpression";
366
+ argument?: Expression | null | undefined;
367
+ delegate: boolean;
368
+ }
369
+ interface TemplateLiteral extends BaseExpression {
370
+ type: "TemplateLiteral";
371
+ quasis: TemplateElement[];
372
+ expressions: Expression[];
373
+ }
374
+ interface TaggedTemplateExpression extends BaseExpression {
375
+ type: "TaggedTemplateExpression";
376
+ tag: Expression;
377
+ quasi: TemplateLiteral;
378
+ }
379
+ interface TemplateElement extends BaseNode {
380
+ type: "TemplateElement";
381
+ tail: boolean;
382
+ value: {
383
+ /** It is null when the template literal is tagged and the text has an invalid escape (e.g. - tag`\unicode and \u{55}`) */cooked?: string | null | undefined;
384
+ raw: string;
385
+ };
386
+ }
387
+ interface AssignmentProperty extends Property {
388
+ value: Pattern;
389
+ kind: "init";
390
+ method: boolean; // false
391
+ }
392
+ interface ObjectPattern extends BasePattern {
393
+ type: "ObjectPattern";
394
+ properties: Array<AssignmentProperty | RestElement>;
395
+ }
396
+ interface ArrayPattern extends BasePattern {
397
+ type: "ArrayPattern";
398
+ elements: Array<Pattern | null>;
399
+ }
400
+ interface RestElement extends BasePattern {
401
+ type: "RestElement";
402
+ argument: Pattern;
403
+ }
404
+ interface AssignmentPattern extends BasePattern {
405
+ type: "AssignmentPattern";
406
+ left: Pattern;
407
+ right: Expression;
408
+ }
409
+ interface BaseClass extends BaseNode {
410
+ superClass?: Expression | null | undefined;
411
+ body: ClassBody;
412
+ }
413
+ interface ClassBody extends BaseNode {
414
+ type: "ClassBody";
415
+ body: Array<MethodDefinition | PropertyDefinition | StaticBlock>;
416
+ }
417
+ interface MethodDefinition extends BaseNode {
418
+ type: "MethodDefinition";
419
+ key: Expression | PrivateIdentifier;
420
+ value: FunctionExpression;
421
+ kind: "constructor" | "method" | "get" | "set";
422
+ computed: boolean;
423
+ static: boolean;
424
+ }
425
+ interface MaybeNamedClassDeclaration extends BaseClass, BaseDeclaration {
426
+ type: "ClassDeclaration";
427
+ /** It is null when a class declaration is a part of the `export default class` statement */
428
+ id: Identifier | null;
429
+ }
430
+ interface ClassDeclaration extends MaybeNamedClassDeclaration {
431
+ id: Identifier;
432
+ }
433
+ interface ClassExpression extends BaseClass, BaseExpression {
434
+ type: "ClassExpression";
435
+ id?: Identifier | null | undefined;
436
+ }
437
+ interface MetaProperty extends BaseExpression {
438
+ type: "MetaProperty";
439
+ meta: Identifier;
440
+ property: Identifier;
441
+ }
442
+ type ModuleDeclaration = ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | ExportAllDeclaration;
443
+ interface BaseModuleDeclaration extends BaseNode {}
444
+ interface BaseModuleSpecifier extends BaseNode {
445
+ local: Identifier;
446
+ }
447
+ interface ImportDeclaration extends BaseModuleDeclaration {
448
+ type: "ImportDeclaration";
449
+ specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier>;
450
+ attributes: ImportAttribute[];
451
+ source: Literal;
452
+ }
453
+ interface ImportSpecifier extends BaseModuleSpecifier {
454
+ type: "ImportSpecifier";
455
+ imported: Identifier | Literal;
456
+ }
457
+ interface ImportAttribute extends BaseNode {
458
+ type: "ImportAttribute";
459
+ key: Identifier | Literal;
460
+ value: Literal;
461
+ }
462
+ interface ImportExpression extends BaseExpression {
463
+ type: "ImportExpression";
464
+ source: Expression;
465
+ options?: Expression | null | undefined;
466
+ }
467
+ interface ImportDefaultSpecifier extends BaseModuleSpecifier {
468
+ type: "ImportDefaultSpecifier";
469
+ }
470
+ interface ImportNamespaceSpecifier extends BaseModuleSpecifier {
471
+ type: "ImportNamespaceSpecifier";
472
+ }
473
+ interface ExportNamedDeclaration extends BaseModuleDeclaration {
474
+ type: "ExportNamedDeclaration";
475
+ declaration?: Declaration | null | undefined;
476
+ specifiers: ExportSpecifier[];
477
+ attributes: ImportAttribute[];
478
+ source?: Literal | null | undefined;
479
+ }
480
+ interface ExportSpecifier extends Omit<BaseModuleSpecifier, "local"> {
481
+ type: "ExportSpecifier";
482
+ local: Identifier | Literal;
483
+ exported: Identifier | Literal;
484
+ }
485
+ interface ExportDefaultDeclaration extends BaseModuleDeclaration {
486
+ type: "ExportDefaultDeclaration";
487
+ declaration: MaybeNamedFunctionDeclaration | MaybeNamedClassDeclaration | Expression;
488
+ }
489
+ interface ExportAllDeclaration extends BaseModuleDeclaration {
490
+ type: "ExportAllDeclaration";
491
+ exported: Identifier | Literal | null;
492
+ attributes: ImportAttribute[];
493
+ source: Literal;
494
+ }
495
+ interface AwaitExpression extends BaseExpression {
496
+ type: "AwaitExpression";
497
+ argument: Expression;
498
+ }
499
+ //#endregion
500
+ //#region src/parse/gts_plugin.d.ts
501
+ interface GtsPluginOption {
502
+ allowEmptyShortcutMember?: boolean;
503
+ allowEmptyPositionalAttribute?: boolean;
504
+ }
505
+ //#endregion
506
+ //#region src/parse/index.d.ts
507
+ interface ParseOptions extends GtsPluginOption {
508
+ onComment: Options["onComment"];
509
+ }
510
+ declare function parse(input: string, options?: ParseOptions): Program;
511
+ interface ParseLooseOptions extends GtsPluginOption {
512
+ recordCallLParens?: boolean;
513
+ }
514
+ declare function parseLoose(input: string, options?: ParseLooseOptions): Program;
15
515
  //#endregion
16
516
  //#region src/transform/gts.d.ts
17
517
  interface TranspileOption {
@@ -87,6 +587,13 @@ interface CodeInformation {
87
587
  }
88
588
  //#endregion
89
589
  //#region src/transform/volar/mappings.d.ts
590
+ declare module "@volar/language-core" {
591
+ interface CodeInformation {
592
+ gtsAttribute?: boolean;
593
+ literalFromId?: boolean;
594
+ directActionStub?: boolean;
595
+ }
596
+ }
90
597
  interface VolarMappingResult {
91
598
  code: string;
92
599
  mappings: CodeMapping[];
@@ -125,4 +632,4 @@ declare function resolveGtsConfigSync(filePath: string, inlineConfig: GtsConfig,
125
632
  declare function transpile(source: string, filename: string, option: TranspileOption): TranspileResult;
126
633
  declare function transpileForVolar(source: string, filename: string, option: TranspileOption): VolarMappingResult;
127
634
  //#endregion
128
- export { type GtsConfig, GtsTranspilerError, type TranspileOption, type TranspileResult, type VolarMappingResult, resolveGtsConfig, resolveGtsConfigSync, transpile, transpileForVolar };
635
+ export { type GtsConfig, type ParseLooseOptions as GtsParseLooseOptions, type ParseOptions as GtsParseOptions, GtsTranspilerError, type TranspileOption, type TranspileResult, type VolarMappingResult, parse, parseLoose, resolveGtsConfig, resolveGtsConfigSync, transpile, transpileForVolar };
package/dist/index.js CHANGED
@@ -527,7 +527,8 @@ function parse(input, options) {
527
527
  ecmaVersion: "latest",
528
528
  sourceType: "module",
529
529
  locations: true,
530
- ranges: true
530
+ ranges: true,
531
+ onComment: options?.onComment
531
532
  });
532
533
  } catch (e) {
533
534
  if (e instanceof SyntaxError && "loc" in e) {
@@ -1549,6 +1550,7 @@ const gtsToTypingsWalker = {
1549
1550
  },
1550
1551
  GTSNamedAttributeDefinition(node, { visit, state }) {
1551
1552
  const { name, body, bindingName } = node;
1553
+ state.attributeNameNodes.add(name);
1552
1554
  const attrName = JSON.stringify(name.type === "Literal" ? String(name.value) : name.name);
1553
1555
  const { lhsId } = enterAttr(state, attrName);
1554
1556
  const positionals = body.positionalAttributes.attributes.map((attr) => {
@@ -1636,14 +1638,28 @@ const gtsToTypingsWalker = {
1636
1638
  GTSNamedAttributeBlock(node, { state, visit }) {
1637
1639
  for (const attr of node.attributes) visit(attr);
1638
1640
  if (node.directAction) {
1641
+ const stubStatement = {
1642
+ type: "ExpressionStatement",
1643
+ expression: {
1644
+ type: "Literal",
1645
+ value: 0
1646
+ }
1647
+ };
1648
+ state.typingPendingStatements.push(stubStatement);
1639
1649
  const attrName = JSON.stringify(state.ActionLit.value);
1640
1650
  const { lhsId } = enterAttr(state, attrName);
1641
1651
  const actionNotExistsReplacementStr = `${lhsId.name}[${attrName}]`;
1642
- if (node.directAction.range) state.extraMappings.push({
1643
- sourceOffset: node.directAction.range[0],
1644
- length: node.directAction.range[1] - node.directAction.range[0],
1645
- generatedNeedle: actionNotExistsReplacementStr
1646
- });
1652
+ if (node.directAction.range) {
1653
+ state.extraMappings.push({
1654
+ sourceOffset: node.directAction.range[0],
1655
+ length: node.directAction.range[1] - node.directAction.range[0],
1656
+ generatedNeedle: actionNotExistsReplacementStr
1657
+ });
1658
+ state.directActionStubRange.set(stubStatement.expression, {
1659
+ start: node.directAction.range[0],
1660
+ end: node.directAction.range[1]
1661
+ });
1662
+ }
1647
1663
  const fn = {
1648
1664
  type: "ArrowFunctionExpression",
1649
1665
  params: state.shortcutFunctionParameters,
@@ -1692,6 +1708,18 @@ const DEFAULT_VOLAR_MAPPING_DATA = {
1692
1708
  structure: true,
1693
1709
  verification: true
1694
1710
  };
1711
+ const ATTRIBUTE_NAME_MAPPING_DATA = {
1712
+ ...DEFAULT_VOLAR_MAPPING_DATA,
1713
+ gtsAttribute: true
1714
+ };
1715
+ const LITERAL_FROM_ID_MAPPING_DATA = {
1716
+ ...DEFAULT_VOLAR_MAPPING_DATA,
1717
+ literalFromId: true
1718
+ };
1719
+ const DIRECT_ACTION_STUB_MAPPING_DATA = {
1720
+ ...DEFAULT_VOLAR_MAPPING_DATA,
1721
+ directActionStub: true
1722
+ };
1695
1723
  const VERIFICATION_ONLY_MAPPING_DATA = { verification: true };
1696
1724
  Object.freeze(DEFAULT_VOLAR_MAPPING_DATA);
1697
1725
  Object.freeze(VERIFICATION_ONLY_MAPPING_DATA);
@@ -1702,6 +1730,7 @@ function getPrintOptions(source, state) {
1702
1730
  source,
1703
1731
  isUntouched: (node) => {
1704
1732
  if (node.type === "Identifier" && node.isDummy) return false;
1733
+ if (state.attributeNameNodes.has(node)) return false;
1705
1734
  return state.sourceNodes.has(node);
1706
1735
  },
1707
1736
  getLeadingComments: (node) => node.leadingComments,
@@ -1715,16 +1744,20 @@ function getPrintOptions(source, state) {
1715
1744
  let firstNonWhiteSpaceIndex = context.source.slice(identifier.range[1]).search(/\S/);
1716
1745
  const rangeEnd = firstNonWhiteSpaceIndex === -1 ? context.source.length : identifier.range[1] + firstNonWhiteSpaceIndex;
1717
1746
  context.writeMapped(text, identifier.range[0], rangeEnd);
1718
- } else return defaultPrinters.Identifier(node, context);
1747
+ } else if (identifier.range && state.attributeNameNodes.has(identifier)) context.writeMapped(identifier.name, identifier.range[0], identifier.range[1], ATTRIBUTE_NAME_MAPPING_DATA);
1748
+ else defaultPrinters.Identifier(node, context);
1719
1749
  },
1720
1750
  Literal(node, context) {
1721
1751
  const generatedStart = context.generatedOffset;
1752
+ let directActionStubRange;
1722
1753
  if (state.literalFromIdentifier.has(node) && node.range) {
1723
1754
  const text = JSON.stringify(node.value);
1724
1755
  context.write("\"");
1725
- context.writeMapped(text.slice(1, -1), node.range[0], node.range[1]);
1756
+ context.writeMapped(text.slice(1, -1), node.range[0], node.range[1], LITERAL_FROM_ID_MAPPING_DATA);
1726
1757
  context.write("\"");
1727
- } else defaultPrinters.Literal(node, context);
1758
+ } 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);
1759
+ 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);
1760
+ else defaultPrinters.Literal(node, context);
1728
1761
  if (state.diagnosticsOnTopNodes.has(node)) {
1729
1762
  const generatedEnd = context.generatedOffset;
1730
1763
  context.createExtraMapping({
@@ -1865,7 +1898,9 @@ function transformForVolar(ast, option, sourceInfo) {
1865
1898
  finalMetaTypeIdStack: [],
1866
1899
  attrsOfCurrentVm: [],
1867
1900
  sourceNodes: /* @__PURE__ */ new WeakSet(),
1901
+ attributeNameNodes: /* @__PURE__ */ new WeakSet(),
1868
1902
  namedAttributeCalleeLParenRange: /* @__PURE__ */ new WeakMap(),
1903
+ directActionStubRange: /* @__PURE__ */ new WeakMap(),
1869
1904
  literalFromIdentifier: /* @__PURE__ */ new WeakSet(),
1870
1905
  lastArgNodes: /* @__PURE__ */ new WeakSet(),
1871
1906
  lastImportDeclarationIfGen: null,
@@ -2010,4 +2045,4 @@ function transpileForVolar(source, filename, option) {
2010
2045
  });
2011
2046
  }
2012
2047
  //#endregion
2013
- export { GtsTranspilerError, resolveGtsConfig, resolveGtsConfigSync, transpile, transpileForVolar };
2048
+ export { GtsTranspilerError, parse, parseLoose, resolveGtsConfig, resolveGtsConfigSync, transpile, transpileForVolar };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gi-tcg/gts-transpiler",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
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.5.2",
25
+ "espolar": "^0.6.0",
26
26
  "esrap": "2.2.1",
27
27
  "magic-string": "^0.30.21",
28
28
  "path-browserify-esm": "^1.0.6",
package/src/index.ts CHANGED
@@ -1,4 +1,9 @@
1
- import { parse, parseLoose } from "./parse/index.ts";
1
+ import {
2
+ parse,
3
+ parseLoose,
4
+ type ParseLooseOptions,
5
+ type ParseOptions,
6
+ } from "./parse/index.ts";
2
7
  import {
3
8
  transform,
4
9
  transformForVolar,
@@ -34,7 +39,14 @@ export function transpileForVolar(
34
39
  });
35
40
  }
36
41
 
37
- export type { TranspileOption, TranspileResult, VolarMappingResult };
42
+ export { parse, parseLoose };
43
+ export type {
44
+ ParseOptions as GtsParseOptions,
45
+ ParseLooseOptions as GtsParseLooseOptions,
46
+ TranspileOption,
47
+ TranspileResult,
48
+ VolarMappingResult,
49
+ };
38
50
  export {
39
51
  resolveGtsConfig,
40
52
  resolveGtsConfigSync,
@@ -1,4 +1,4 @@
1
- import { Parser } from "acorn";
1
+ import { Parser, type Options } from "acorn";
2
2
  import type { Position, Program } from "estree";
3
3
  import { tsPlugin } from "@sveltejs/acorn-typescript";
4
4
  import { gtsPlugin, type GtsPluginOption } from "./gts_plugin.ts";
@@ -9,7 +9,11 @@ import { recordCallLParenPlugin } from "./record_call_lparen_plugin.ts";
9
9
 
10
10
  const TsParser = Parser.extend(tsPlugin());
11
11
 
12
- export function parse(input: string, options?: GtsPluginOption): Program {
12
+ export interface ParseOptions extends GtsPluginOption {
13
+ onComment: Options["onComment"];
14
+ }
15
+
16
+ export function parse(input: string, options?: ParseOptions): Program {
13
17
  try {
14
18
  const GtsParser = TsParser.extend(gtsPlugin(options));
15
19
  return GtsParser.parse(input, {
@@ -17,6 +21,7 @@ export function parse(input: string, options?: GtsPluginOption): Program {
17
21
  sourceType: "module",
18
22
  locations: true,
19
23
  ranges: true,
24
+ onComment: options?.onComment,
20
25
  }) as Program;
21
26
  } catch (e) {
22
27
  if (e instanceof SyntaxError && "loc" in e) {
@@ -41,7 +41,9 @@ export function transformForVolar(
41
41
  attrsOfCurrentVm: [],
42
42
 
43
43
  sourceNodes: new WeakSet(),
44
+ attributeNameNodes: new WeakSet(),
44
45
  namedAttributeCalleeLParenRange: new WeakMap(),
46
+ directActionStubRange: new WeakMap(),
45
47
  literalFromIdentifier: new WeakSet(),
46
48
  lastArgNodes: new WeakSet(),
47
49
  lastImportDeclarationIfGen: null,
@@ -1,5 +1,13 @@
1
1
  import type { CodeInformation, CodeMapping } from "@volar/language-core";
2
2
 
3
+ declare module "@volar/language-core" {
4
+ export interface CodeInformation {
5
+ gtsAttribute?: boolean;
6
+ literalFromId?: boolean;
7
+ directActionStub?: boolean;
8
+ }
9
+ }
10
+
3
11
  export interface VolarMappingResult {
4
12
  code: string;
5
13
  mappings: CodeMapping[];
@@ -13,6 +21,18 @@ export const DEFAULT_VOLAR_MAPPING_DATA: CodeInformation = {
13
21
  structure: true,
14
22
  verification: true,
15
23
  };
24
+ export const ATTRIBUTE_NAME_MAPPING_DATA: CodeInformation = {
25
+ ...DEFAULT_VOLAR_MAPPING_DATA,
26
+ gtsAttribute: true,
27
+ }
28
+ export const LITERAL_FROM_ID_MAPPING_DATA: CodeInformation = {
29
+ ...DEFAULT_VOLAR_MAPPING_DATA,
30
+ literalFromId: true,
31
+ }
32
+ export const DIRECT_ACTION_STUB_MAPPING_DATA: CodeInformation = {
33
+ ...DEFAULT_VOLAR_MAPPING_DATA,
34
+ directActionStub: true,
35
+ }
16
36
  export const VERIFICATION_ONLY_MAPPING_DATA: CodeInformation = {
17
37
  verification: true,
18
38
  };
@@ -1,5 +1,6 @@
1
1
  import type {
2
2
  Identifier,
3
+ Literal,
3
4
  NewExpression,
4
5
  Node,
5
6
  SimpleCallExpression,
@@ -8,10 +9,14 @@ import {
8
9
  type PrintOptions,
9
10
  type AST as EspolarAST,
10
11
  defaultPrinters,
12
+ type SourceRange,
11
13
  } from "espolar";
12
14
  import type { CodeInformation } from "@volar/language-core";
13
15
  import {
16
+ ATTRIBUTE_NAME_MAPPING_DATA,
14
17
  DEFAULT_VOLAR_MAPPING_DATA,
18
+ DIRECT_ACTION_STUB_MAPPING_DATA,
19
+ LITERAL_FROM_ID_MAPPING_DATA,
15
20
  VERIFICATION_ONLY_MAPPING_DATA,
16
21
  } from "./mappings.ts";
17
22
  import type { TypingTranspileState } from "./walker.ts";
@@ -26,19 +31,25 @@ export function getPrintOptions(
26
31
  if (node.type === "Identifier" && (node as Identifier).isDummy) {
27
32
  return false;
28
33
  }
34
+ if (state.attributeNameNodes.has(node as Identifier | Literal)) {
35
+ return false;
36
+ }
29
37
  return state.sourceNodes.has(node as Node);
30
38
  },
31
39
  getLeadingComments: (node) => (node as Node).leadingComments,
32
40
  getTrailingComments: (node) => (node as Node).trailingComments,
33
41
  getMappingData: () => DEFAULT_VOLAR_MAPPING_DATA,
34
42
  printers: {
35
- // Make the print of dummy identifier print nothing.
36
- // Exception: if GTS attribute list's last argument is dummy, e.g.
37
- // foo bar, ;
38
- // ^~ here
39
- // Then the printed JS will be `foo(bar, )` which WILL NOT be syntax error in ES6.
40
- // So we mark the lastArg manually and print an additional comma
41
- // for this dummy identifier, i.e. `foo(bar,,)` and TypeScript will recognize the error.
43
+ // 1) Make the print of dummy identifier print nothing.
44
+ // Exception: if GTS attribute list's last argument is dummy, e.g.
45
+ // foo bar, ;
46
+ // ^~ here
47
+ // Then the printed JS will be `foo(bar, )` which WILL NOT be syntax error in ES6.
48
+ // So we mark the lastArg manually and print an additional comma
49
+ // for this dummy identifier, i.e. `foo(bar,,)` and TypeScript will recognize the error.
50
+ // 2) Add mapping data "gtsAttribute" to GTS attribute name identifiers and literals.
51
+ // This will be recognized as "*.gtsAttribute" semantic token in language service plugin
52
+ // and remapped to "emphasis" in the language client that rendered as italic.
42
53
  Identifier(node, context) {
43
54
  const identifier = node as Identifier;
44
55
  if (identifier.isDummy && identifier.range) {
@@ -52,17 +63,52 @@ export function getPrintOptions(
52
63
  ? context.source.length
53
64
  : identifier.range[1] + firstNonWhiteSpaceIndex;
54
65
  context.writeMapped(text, identifier.range[0], rangeEnd);
66
+ } else if (
67
+ identifier.range &&
68
+ state.attributeNameNodes.has(identifier)
69
+ ) {
70
+ context.writeMapped(
71
+ identifier.name,
72
+ identifier.range[0],
73
+ identifier.range[1],
74
+ ATTRIBUTE_NAME_MAPPING_DATA,
75
+ );
55
76
  } else {
56
- return defaultPrinters.Identifier(node, context);
77
+ defaultPrinters.Identifier(node, context);
57
78
  }
58
79
  },
59
80
  Literal(node, context) {
60
81
  const generatedStart = context.generatedOffset;
82
+ let directActionStubRange: SourceRange | undefined;
61
83
  if (state.literalFromIdentifier.has(node) && node.range) {
84
+ // For string literals generated from identifiers, add mappings from only the content of literal
85
+ // to the identifier, so the highlight, auto-complete, etc. will work correctly.
62
86
  const text = JSON.stringify(node.value);
63
87
  context.write('"');
64
- context.writeMapped(text.slice(1, -1), node.range[0], node.range[1]);
88
+ context.writeMapped(
89
+ text.slice(1, -1),
90
+ node.range[0],
91
+ node.range[1],
92
+ LITERAL_FROM_ID_MAPPING_DATA,
93
+ );
65
94
  context.write('"');
95
+ } else if (state.attributeNameNodes.has(node) && node.range) {
96
+ context.writeMapped(
97
+ node.raw ?? JSON.stringify((node as EspolarAST.Literal).value),
98
+ node.range[0],
99
+ node.range[1],
100
+ ATTRIBUTE_NAME_MAPPING_DATA,
101
+ );
102
+ } else if ((directActionStubRange = state.directActionStubRange.get(node))) {
103
+ // For direct action stubs, add mappings from this expression statement line to the
104
+ // start of original direct action start position. Add `directActionStub` data
105
+ // for recognizing them in language service plugin.
106
+ context.writeMapped(
107
+ node.raw ?? JSON.stringify((node as EspolarAST.Literal).value),
108
+ directActionStubRange.start,
109
+ directActionStubRange.start + 1,
110
+ DIRECT_ACTION_STUB_MAPPING_DATA,
111
+ )
66
112
  } else {
67
113
  defaultPrinters.Literal(node, context);
68
114
  }
@@ -54,11 +54,19 @@ export interface TypingTranspileState extends TranspileState {
54
54
  replacementTag: Identifier;
55
55
  /** untouched source nodes */
56
56
  sourceNodes: WeakSet<Node>;
57
+ /** GTS' attribute name nodes */
58
+ attributeNameNodes: WeakSet<Identifier | Literal>;
57
59
  /**
58
- * The callee of typing source of GTS' attribute names. Map the character
60
+ * For each callee of typing source of GTS' attribute names, map the character
59
61
  * after the name (typically whitespace) as the lParen of CallExpression
60
62
  */
61
63
  namedAttributeCalleeLParenRange: WeakMap<Node, SourceRange>;
64
+ /**
65
+ * For each GTSDirectFunction, map a generated stub statement to the range of
66
+ * GTSDirectFunction itself. This extra mapping is used to insert CodeLens that
67
+ * mark the start position of direct action body.
68
+ */
69
+ directActionStubRange: WeakMap<Node, SourceRange>;
62
70
  /**
63
71
  * String literal nodes that are derived from identifiers.
64
72
  * - sourceStart += 1
@@ -325,12 +333,14 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
325
333
  state.diagnosticsOnTopNodes.add(specifier);
326
334
  }
327
335
  }
328
- const lastImportDecl = importDecls.pop() ?? {
329
- type: "ImportDeclaration",
330
- specifiers: [],
331
- source: { type: "Literal", value: "" },
332
- attributes: [],
333
- } satisfies ImportDeclaration;
336
+ const lastImportDecl =
337
+ importDecls.pop() ??
338
+ ({
339
+ type: "ImportDeclaration",
340
+ specifiers: [],
341
+ source: { type: "Literal", value: "" },
342
+ attributes: [],
343
+ } satisfies ImportDeclaration);
334
344
  body.unshift(
335
345
  ...importDecls,
336
346
  // Add an unrelated statement between system generated imports to make them unsorted,
@@ -342,7 +352,7 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
342
352
  expression: {
343
353
  type: "Literal",
344
354
  value: 0,
345
- }
355
+ },
346
356
  },
347
357
  lastImportDecl,
348
358
  createReplacementHolder(state, {
@@ -362,6 +372,7 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
362
372
  },
363
373
  GTSNamedAttributeDefinition(node, { visit, state }) {
364
374
  const { name, body, bindingName } = node;
375
+ state.attributeNameNodes.add(name);
365
376
  const attrName = JSON.stringify(
366
377
  name.type === "Literal" ? String(name.value) : name.name,
367
378
  );
@@ -462,6 +473,11 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
462
473
  visit(attr);
463
474
  }
464
475
  if (node.directAction) {
476
+ const stubStatement: ExpressionStatement = {
477
+ type: "ExpressionStatement",
478
+ expression: { type: "Literal", value: 0 },
479
+ };
480
+ state.typingPendingStatements.push(stubStatement);
465
481
  const attrName = JSON.stringify(state.ActionLit.value);
466
482
  const { lhsId } = enterAttr(state, attrName);
467
483
  const actionNotExistsReplacementStr = `${lhsId.name}[${attrName}]`;
@@ -471,6 +487,10 @@ export const gtsToTypingsWalker: Visitors<Node, TypingTranspileState> = {
471
487
  length: node.directAction.range[1] - node.directAction.range[0],
472
488
  generatedNeedle: actionNotExistsReplacementStr,
473
489
  });
490
+ state.directActionStubRange.set(stubStatement.expression, {
491
+ start: node.directAction.range[0],
492
+ end: node.directAction.range[1],
493
+ });
474
494
  }
475
495
  const fn: ArrowFunctionExpression = {
476
496
  type: "ArrowFunctionExpression",
@@ -1,90 +0,0 @@
1
- import type { Node, Program, SourceLocation } from "estree";
2
- import { walk } from "zimmerframe";
3
-
4
- export interface LeafToken {
5
- loc: SourceLocation;
6
- isDummy?: boolean;
7
- /**
8
- * Override source length (instead of loc.end - loc.start)
9
- */
10
- sourceLength?: number;
11
- /**
12
- * Adjust the start position of source code
13
- */
14
- sourceStartOffset?: number;
15
- /**
16
- * Adjust the start position of generated code
17
- */
18
- generatedStartOffset?: number;
19
- /**
20
- * Make the source length longer
21
- */
22
- sourceLengthOffset?: number;
23
- /**
24
- * The original length of generated code, used for mapping diagnostics
25
- */
26
- generatedLength?: number;
27
- }
28
-
29
- export function collectLeafTokens(source: string, ast: Program): LeafToken[] {
30
- interface CollectTokenState {
31
- tokens: LeafToken[];
32
- /** Whether the node is from source and purely TypeScript */
33
- pureSource: boolean;
34
- /** Whether the node is visited once (for detecting leaf node) */
35
- visited: boolean;
36
- }
37
- const state: CollectTokenState = {
38
- tokens: [],
39
- pureSource: true,
40
- visited: false,
41
- };
42
- walk(ast as Node, state, {
43
- _(node, { state, next }) {
44
- state.visited = true;
45
- let currNodePureSource = !!node.loc && !node.type.startsWith("GTS");
46
- const subState = { tokens: [], pureSource: true, visited: false };
47
- next(subState);
48
- currNodePureSource &&= subState.pureSource;
49
- state.pureSource &&= currNodePureSource;
50
- // record original source for purely branch node
51
- if (subState.visited && node.range && currNodePureSource) {
52
- const [start, end] = node.range;
53
- node.pureSource = source.slice(start, end);
54
- }
55
- if (currNodePureSource) {
56
- const token: LeafToken = {
57
- loc: node.loc!,
58
- };
59
- if ("isDummy" in node && node.isDummy) {
60
- token.isDummy = true;
61
- token.sourceLength = 0;
62
- // add 1 for squiggle on next character
63
- token.generatedLength = 1;
64
- }
65
- state.tokens.push(token);
66
- } else {
67
- state.tokens.push(...subState.tokens);
68
- }
69
- },
70
- NewExpression(node, { state, next }) {
71
- const lParenLoc = node.lParenLoc;
72
- if (lParenLoc) {
73
- state.tokens.push({
74
- loc: lParenLoc,
75
- });
76
- }
77
- next();
78
- },
79
- CallExpression(node, { state, next }) {
80
- const lParenLoc = node.lParenLoc;
81
- if (lParenLoc) {
82
- state.tokens.push({
83
- loc: lParenLoc,
84
- });
85
- }
86
- next();
87
- },
88
- });
89
- return state.tokens;
90
- }