@gi-tcg/gts-transpiler 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/index.d.ts +109 -20
- package/dist/index.js +1837 -2178
- package/package.json +11 -7
- package/src/config.ts +1 -1
- package/src/error.ts +3 -4
- package/src/index.ts +6 -6
- package/src/parse/gts_plugin.ts +5 -5
- package/src/parse/index.ts +6 -4
- package/src/parse/loose_plugin.ts +1 -1
- package/src/parse/record_call_lparen_plugin.ts +18 -21
- package/src/transform/erase_ts.ts +2 -2
- package/src/transform/gts.ts +17 -3
- package/src/transform/index.ts +6 -6
- package/src/transform/volar/collect_tokens.ts +28 -34
- package/src/transform/volar/index.ts +52 -52
- package/src/transform/volar/mappings.ts +5 -352
- package/src/transform/volar/printer.ts +101 -117
- package/src/transform/volar/replacements.ts +76 -48
- package/src/transform/volar/walker.ts +89 -70
- package/src/types.ts +5 -11
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gi-tcg/gts-transpiler",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"repository": "https://github.com/piovium/gts.git",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
|
-
"
|
|
10
|
+
"development": "./src/index.ts",
|
|
11
11
|
"default": "./dist/index.js"
|
|
12
12
|
}
|
|
13
13
|
},
|
|
@@ -15,19 +15,23 @@
|
|
|
15
15
|
"src",
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
|
-
"scripts": {},
|
|
19
18
|
"dependencies": {
|
|
20
|
-
"@jridgewell/sourcemap-codec": "^1.5.5",
|
|
21
19
|
"@sveltejs/acorn-typescript": "^1.0.8",
|
|
22
|
-
"acorn": "8.15.0",
|
|
20
|
+
"acorn": "^8.15.0",
|
|
21
|
+
"dedent": "^1.7.2",
|
|
22
|
+
"espolar": "^0.2.1",
|
|
23
23
|
"esrap": "2.2.1",
|
|
24
24
|
"magic-string": "^0.30.21",
|
|
25
25
|
"path-browserify-esm": "^1.0.6",
|
|
26
26
|
"zimmerframe": "^1.1.4"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
+
"@types/estree": "^1.0.9",
|
|
29
30
|
"@types/node": "^24.3.0",
|
|
30
|
-
"@types/estree": "^1.0.8",
|
|
31
31
|
"@volar/language-core": "^2.4.27"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsdown --platform neutral",
|
|
35
|
+
"test": "vitest"
|
|
32
36
|
}
|
|
33
|
-
}
|
|
37
|
+
}
|
package/src/config.ts
CHANGED
package/src/error.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { SourceLocation } from "estree";
|
|
2
2
|
|
|
3
3
|
export class GtsTranspilerError extends Error {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
public readonly position: SourceLocation | null,
|
|
7
|
-
) {
|
|
4
|
+
public readonly position: SourceLocation | null;
|
|
5
|
+
constructor(message: string, position: SourceLocation | null) {
|
|
8
6
|
super(message);
|
|
9
7
|
this.name = "GtsTranspilerError";
|
|
8
|
+
this.position = position;
|
|
10
9
|
}
|
|
11
10
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { parse, parseLoose } from "./parse";
|
|
1
|
+
import { parse, parseLoose } from "./parse/index.ts";
|
|
2
2
|
import {
|
|
3
3
|
transform,
|
|
4
4
|
transformForVolar,
|
|
5
5
|
type TranspileResult,
|
|
6
|
-
} from "./transform";
|
|
7
|
-
import type { TranspileOption } from "./transform/gts";
|
|
8
|
-
import type { VolarMappingResult } from "./transform/volar";
|
|
9
|
-
export { GtsTranspilerError } from "./error";
|
|
6
|
+
} from "./transform/index.ts";
|
|
7
|
+
import type { TranspileOption } from "./transform/gts.ts";
|
|
8
|
+
import type { VolarMappingResult } from "./transform/volar/index.ts";
|
|
9
|
+
export { GtsTranspilerError } from "./error.ts";
|
|
10
10
|
|
|
11
11
|
export function transpile(
|
|
12
12
|
source: string,
|
|
@@ -39,4 +39,4 @@ export {
|
|
|
39
39
|
resolveGtsConfig,
|
|
40
40
|
resolveGtsConfigSync,
|
|
41
41
|
type GtsConfig,
|
|
42
|
-
} from "./config";
|
|
42
|
+
} from "./config.ts";
|
package/src/parse/gts_plugin.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tokTypes, type Parser as ParserClass } from "acorn";
|
|
2
|
-
import type { Parse, AST } from "../types";
|
|
3
|
-
import { specialIdentifiers } from "../keywords";
|
|
4
|
-
import { DUMMY_PLACEHOLDER } from "./loose_plugin";
|
|
2
|
+
import type { Parse, AST } from "../types.ts";
|
|
3
|
+
import { specialIdentifiers } from "../keywords.ts";
|
|
4
|
+
import { DUMMY_PLACEHOLDER } from "./loose_plugin.ts";
|
|
5
5
|
|
|
6
6
|
/*
|
|
7
7
|
|
|
@@ -251,7 +251,7 @@ export function gtsPlugin(options: GtsPluginOption = {}) {
|
|
|
251
251
|
this.isContextual("as"))
|
|
252
252
|
) {
|
|
253
253
|
// Allow omitting the attribute expression for language tooling
|
|
254
|
-
const dummy = this.
|
|
254
|
+
const dummy = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc) as AST.Identifier;
|
|
255
255
|
dummy.name = DUMMY_PLACEHOLDER;
|
|
256
256
|
dummy.isDummy = true;
|
|
257
257
|
return this.finishNode(dummy, "Identifier");
|
|
@@ -297,7 +297,7 @@ export function gtsPlugin(options: GtsPluginOption = {}) {
|
|
|
297
297
|
this.type !== tokTypes.name
|
|
298
298
|
) {
|
|
299
299
|
// Allow omitting the identifier after ':' for language tooling
|
|
300
|
-
const dummy = this.
|
|
300
|
+
const dummy = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc) as AST.Identifier;
|
|
301
301
|
dummy.name = DUMMY_PLACEHOLDER;
|
|
302
302
|
dummy.isDummy = true;
|
|
303
303
|
node.property = this.finishNode(dummy, "Identifier");
|
package/src/parse/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Parser } from "acorn";
|
|
2
2
|
import type { Position, Program } from "estree";
|
|
3
3
|
import { tsPlugin } from "@sveltejs/acorn-typescript";
|
|
4
|
-
import { gtsPlugin, type GtsPluginOption } from "./gts_plugin.
|
|
5
|
-
import { loosePlugin } from "./loose_plugin.
|
|
4
|
+
import { gtsPlugin, type GtsPluginOption } from "./gts_plugin.ts";
|
|
5
|
+
import { loosePlugin } from "./loose_plugin.ts";
|
|
6
6
|
import { getCommentHandlers } from "./comment.js";
|
|
7
|
-
import { GtsTranspilerError } from "../error.
|
|
8
|
-
import { recordCallLParenPlugin } from "./record_call_lparen_plugin.
|
|
7
|
+
import { GtsTranspilerError } from "../error.ts";
|
|
8
|
+
import { recordCallLParenPlugin } from "./record_call_lparen_plugin.ts";
|
|
9
9
|
|
|
10
10
|
const TsParser = Parser.extend(tsPlugin());
|
|
11
11
|
|
|
@@ -16,6 +16,7 @@ export function parse(input: string, options?: GtsPluginOption): Program {
|
|
|
16
16
|
ecmaVersion: "latest",
|
|
17
17
|
sourceType: "module",
|
|
18
18
|
locations: true,
|
|
19
|
+
ranges: true,
|
|
19
20
|
}) as Program;
|
|
20
21
|
} catch (e) {
|
|
21
22
|
if (e instanceof SyntaxError && "loc" in e) {
|
|
@@ -54,6 +55,7 @@ export function parseLoose(
|
|
|
54
55
|
ecmaVersion: "latest",
|
|
55
56
|
sourceType: "module",
|
|
56
57
|
locations: true,
|
|
58
|
+
ranges: true,
|
|
57
59
|
onComment,
|
|
58
60
|
}) as Program;
|
|
59
61
|
addComments(ast);
|
|
@@ -29,7 +29,7 @@ export function loosePlugin() {
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
createDummyIdentifier() {
|
|
32
|
-
const dummy = this.
|
|
32
|
+
const dummy = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc) as AST.Identifier;
|
|
33
33
|
dummy.name = DUMMY_PLACEHOLDER;
|
|
34
34
|
dummy.isDummy = true;
|
|
35
35
|
return this.finishNode(dummy, "Identifier");
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { tokTypes, type Parser } from "acorn";
|
|
2
|
-
import type { AST, Parse } from "../types.
|
|
2
|
+
import type { AST, Parse } from "../types.ts";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* A plugin that records the location of the left parenthesis in CallExpression and
|
|
5
|
+
* A plugin that records the location of the left parenthesis in CallExpression and
|
|
6
6
|
* NewExpression.
|
|
7
|
-
*
|
|
8
|
-
* This is useful for Language tooling, that we can maps the '(' token from its location,
|
|
9
|
-
* to provide * a signature help for user when they press `(` after a function name.
|
|
10
7
|
*
|
|
11
|
-
*
|
|
8
|
+
* This is useful for Language tooling, that we can maps the '(' token from its location,
|
|
9
|
+
* to provide a signature help for user when they press `(` after a function name.
|
|
10
|
+
*
|
|
11
|
+
* The recorded location will be stored in `lParenLoc` property of the
|
|
12
12
|
* CallExpression/NewExpression node.
|
|
13
|
-
* @returns
|
|
13
|
+
* @returns the plugin function
|
|
14
14
|
*/
|
|
15
15
|
export function recordCallLParenPlugin() {
|
|
16
16
|
return function recordCallLParenPluginTransformer(
|
|
@@ -26,12 +26,9 @@ export function recordCallLParenPlugin() {
|
|
|
26
26
|
optionalChained?: boolean,
|
|
27
27
|
forInit?: boolean | "await",
|
|
28
28
|
): AST.Expression {
|
|
29
|
-
let recordedLParenLoc:
|
|
29
|
+
let recordedLParenLoc: [number, number] | null = null;
|
|
30
30
|
if (!noCalls && this.type === tokTypes.parenL) {
|
|
31
|
-
recordedLParenLoc =
|
|
32
|
-
start: this.startLoc,
|
|
33
|
-
end: this.endLoc,
|
|
34
|
-
};
|
|
31
|
+
recordedLParenLoc = [this.start, this.end];
|
|
35
32
|
}
|
|
36
33
|
const result = super.parseSubscript(
|
|
37
34
|
base,
|
|
@@ -43,18 +40,15 @@ export function recordCallLParenPlugin() {
|
|
|
43
40
|
forInit,
|
|
44
41
|
);
|
|
45
42
|
if (recordedLParenLoc && result.type === "CallExpression") {
|
|
46
|
-
result.
|
|
43
|
+
result.lParenRange = recordedLParenLoc;
|
|
47
44
|
}
|
|
48
45
|
return result;
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
private
|
|
48
|
+
private _capturedLParenRangeFromNew: [number, number] | null = null;
|
|
52
49
|
private readonly _patchedEat = (type: any) => {
|
|
53
50
|
if (type === tokTypes.parenL) {
|
|
54
|
-
this.
|
|
55
|
-
start: this.startLoc,
|
|
56
|
-
end: this.endLoc,
|
|
57
|
-
};
|
|
51
|
+
this._capturedLParenRangeFromNew = [this.start, this.end];
|
|
58
52
|
}
|
|
59
53
|
return this.eat(type);
|
|
60
54
|
};
|
|
@@ -74,9 +68,12 @@ export function recordCallLParenPlugin() {
|
|
|
74
68
|
|
|
75
69
|
override parseNew() {
|
|
76
70
|
const result = super.parseNew.apply(this.#proxiedThis);
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
if (
|
|
72
|
+
this._capturedLParenRangeFromNew &&
|
|
73
|
+
result.type === "NewExpression"
|
|
74
|
+
) {
|
|
75
|
+
result.lParenRange = this._capturedLParenRangeFromNew;
|
|
76
|
+
this._capturedLParenRangeFromNew = null;
|
|
80
77
|
}
|
|
81
78
|
return result;
|
|
82
79
|
}
|
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
Node,
|
|
8
8
|
EmptyStatement,
|
|
9
9
|
} from "estree";
|
|
10
|
-
import { GtsTranspilerError } from "../error";
|
|
10
|
+
import { GtsTranspilerError } from "../error.ts";
|
|
11
11
|
|
|
12
12
|
const empty: EmptyStatement = {
|
|
13
13
|
type: "EmptyStatement",
|
|
@@ -201,4 +201,4 @@ const eraseTsVisitor: Visitors<any, null> = {
|
|
|
201
201
|
|
|
202
202
|
export const eraseTs = <T>(ast: T): T => {
|
|
203
203
|
return walk(ast, null, eraseTsVisitor);
|
|
204
|
-
}
|
|
204
|
+
}
|
package/src/transform/gts.ts
CHANGED
|
@@ -16,11 +16,11 @@ import type {
|
|
|
16
16
|
Statement,
|
|
17
17
|
} from "estree";
|
|
18
18
|
import { walk, type Visitors } from "zimmerframe";
|
|
19
|
-
import { GtsTranspilerError } from "../error";
|
|
19
|
+
import { GtsTranspilerError } from "../error.ts";
|
|
20
20
|
import {
|
|
21
21
|
DEFAULT_QUERY_BINDINGS,
|
|
22
22
|
DEFAULT_SHORTCUT_FUNCTION_PRELUDES,
|
|
23
|
-
} from "./constants";
|
|
23
|
+
} from "./constants.ts";
|
|
24
24
|
|
|
25
25
|
export interface ExternalizedBinding {
|
|
26
26
|
bindingName: Identifier;
|
|
@@ -66,6 +66,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
66
66
|
shorthand: false,
|
|
67
67
|
value: state.ActionLit,
|
|
68
68
|
loc: node.loc,
|
|
69
|
+
range: node.range,
|
|
69
70
|
},
|
|
70
71
|
{
|
|
71
72
|
type: "Property",
|
|
@@ -108,6 +109,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
108
109
|
},
|
|
109
110
|
],
|
|
110
111
|
loc: node.loc,
|
|
112
|
+
range: node.range,
|
|
111
113
|
};
|
|
112
114
|
},
|
|
113
115
|
GTSShortcutFunctionExpression(
|
|
@@ -120,6 +122,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
120
122
|
body: visit(node.body) as Expression | BlockStatement,
|
|
121
123
|
expression: node.expression,
|
|
122
124
|
loc: node.loc,
|
|
125
|
+
range: node.range,
|
|
123
126
|
};
|
|
124
127
|
},
|
|
125
128
|
GTSShortcutArgumentExpression(node, { state, visit }): MemberExpression {
|
|
@@ -130,6 +133,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
130
133
|
optional: false,
|
|
131
134
|
property: visit(node.property) as Identifier,
|
|
132
135
|
loc: node.loc,
|
|
136
|
+
range: node.range,
|
|
133
137
|
};
|
|
134
138
|
},
|
|
135
139
|
GTSQueryExpression(node, { state, visit }) {
|
|
@@ -146,6 +150,7 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
146
150
|
params: state.queryParameters,
|
|
147
151
|
expression: true,
|
|
148
152
|
loc: node.argument.loc,
|
|
153
|
+
range: node.argument.range,
|
|
149
154
|
},
|
|
150
155
|
{
|
|
151
156
|
type: "ObjectExpression",
|
|
@@ -174,7 +179,6 @@ export const commonGtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
174
179
|
],
|
|
175
180
|
},
|
|
176
181
|
],
|
|
177
|
-
// loc: node.loc,
|
|
178
182
|
};
|
|
179
183
|
},
|
|
180
184
|
};
|
|
@@ -279,6 +283,7 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
279
283
|
},
|
|
280
284
|
],
|
|
281
285
|
loc: node.loc,
|
|
286
|
+
range: node.range,
|
|
282
287
|
});
|
|
283
288
|
|
|
284
289
|
state.bindingStatements.push({
|
|
@@ -297,6 +302,7 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
297
302
|
},
|
|
298
303
|
],
|
|
299
304
|
loc: node.loc,
|
|
305
|
+
range: node.range,
|
|
300
306
|
});
|
|
301
307
|
|
|
302
308
|
for (let i = 0; i < newBindings.length; i++) {
|
|
@@ -338,6 +344,7 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
338
344
|
arguments: [state.rootVmId, nodeVarId],
|
|
339
345
|
},
|
|
340
346
|
loc: node.loc,
|
|
347
|
+
range: node.range,
|
|
341
348
|
};
|
|
342
349
|
},
|
|
343
350
|
GTSNamedAttributeDefinition(node, { visit, state }) {
|
|
@@ -363,6 +370,7 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
363
370
|
shorthand: false,
|
|
364
371
|
value: nameValue,
|
|
365
372
|
loc: node.loc,
|
|
373
|
+
range: node.range,
|
|
366
374
|
});
|
|
367
375
|
const body = { ...namedBody, properties };
|
|
368
376
|
if (node.bindingName) {
|
|
@@ -414,8 +422,10 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
414
422
|
body: positionals,
|
|
415
423
|
expression: true,
|
|
416
424
|
loc: positionals.loc,
|
|
425
|
+
range: positionals.range,
|
|
417
426
|
},
|
|
418
427
|
loc: positionals.loc,
|
|
428
|
+
range: positionals.range,
|
|
419
429
|
},
|
|
420
430
|
{
|
|
421
431
|
type: "Property",
|
|
@@ -426,9 +436,11 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
426
436
|
shorthand: false,
|
|
427
437
|
value: named,
|
|
428
438
|
loc: named.loc,
|
|
439
|
+
range: named.range,
|
|
429
440
|
},
|
|
430
441
|
],
|
|
431
442
|
loc: node.loc,
|
|
443
|
+
range: node.range,
|
|
432
444
|
};
|
|
433
445
|
return partialBody;
|
|
434
446
|
},
|
|
@@ -447,6 +459,7 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
447
459
|
}
|
|
448
460
|
}),
|
|
449
461
|
loc: node.loc,
|
|
462
|
+
range: node.range,
|
|
450
463
|
};
|
|
451
464
|
},
|
|
452
465
|
GTSNamedAttributeBlock(node, { visit }): ObjectExpression {
|
|
@@ -471,6 +484,7 @@ const gtsVisitor: Visitors<Node, TranspileState> = {
|
|
|
471
484
|
},
|
|
472
485
|
],
|
|
473
486
|
loc: node.loc,
|
|
487
|
+
range: node.range,
|
|
474
488
|
};
|
|
475
489
|
},
|
|
476
490
|
...commonGtsVisitor,
|
package/src/transform/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Program } from "estree";
|
|
2
|
-
import { eraseTs } from "./erase_ts";
|
|
3
|
-
import { print } from "esrap";
|
|
2
|
+
import { eraseTs } from "./erase_ts.ts";
|
|
3
|
+
import { print, type Visitors } from "esrap";
|
|
4
4
|
import jsPrinter from "esrap/languages/ts";
|
|
5
5
|
import type { SourceMap } from "magic-string";
|
|
6
|
-
import { gtsToTs, type TranspileOption } from "./gts";
|
|
6
|
+
import { gtsToTs, type TranspileOption } from "./gts.ts";
|
|
7
7
|
|
|
8
8
|
export interface TranspileResult {
|
|
9
9
|
code: string;
|
|
@@ -18,11 +18,11 @@ export interface SourceInfo {
|
|
|
18
18
|
export function transform(
|
|
19
19
|
ast: Program,
|
|
20
20
|
option: TranspileOption = {},
|
|
21
|
-
sourceInfo: SourceInfo = {}
|
|
21
|
+
sourceInfo: SourceInfo = {},
|
|
22
22
|
): TranspileResult {
|
|
23
23
|
const ts = gtsToTs(ast, option);
|
|
24
24
|
const js = eraseTs(ts);
|
|
25
|
-
const { code, map } = print(js, jsPrinter(), {
|
|
25
|
+
const { code, map } = print(js, jsPrinter() as Visitors, {
|
|
26
26
|
indent: " ",
|
|
27
27
|
sourceMapContent: sourceInfo.content,
|
|
28
28
|
sourceMapSource: sourceInfo.filename,
|
|
@@ -33,4 +33,4 @@ export function transform(
|
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export { transformForVolar } from "./volar";
|
|
36
|
+
export { transformForVolar } from "./volar/index.ts";
|
|
@@ -1,33 +1,6 @@
|
|
|
1
|
-
import type { Node, SourceLocation } from "estree";
|
|
1
|
+
import type { Node, Program, SourceLocation } from "estree";
|
|
2
2
|
import { walk } from "zimmerframe";
|
|
3
3
|
|
|
4
|
-
function isLeafNode(node: any): boolean {
|
|
5
|
-
for (const key in node) {
|
|
6
|
-
const val = node[key];
|
|
7
|
-
|
|
8
|
-
// Ignore non-child properties (metadata)
|
|
9
|
-
if (key === "loc" || key === "start" || key === "end" || key === "range") {
|
|
10
|
-
continue;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// Check if the property is a Node
|
|
14
|
-
// (An object with a 'type' property is generally an AST node)
|
|
15
|
-
if (val && typeof val === "object" && typeof val.type === "string") {
|
|
16
|
-
return false; // Found a valid child node
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Check if the property is an Array of Nodes (e.g., body: [...])
|
|
20
|
-
if (
|
|
21
|
-
Array.isArray(val) &&
|
|
22
|
-
val.length > 0 &&
|
|
23
|
-
typeof val[0].type === "string"
|
|
24
|
-
) {
|
|
25
|
-
return false; // Found an array of child nodes
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
4
|
export interface LeafToken {
|
|
32
5
|
loc: SourceLocation;
|
|
33
6
|
isDummy?: boolean;
|
|
@@ -53,15 +26,35 @@ export interface LeafToken {
|
|
|
53
26
|
generatedLength?: number;
|
|
54
27
|
}
|
|
55
28
|
|
|
56
|
-
export function collectLeafTokens(ast:
|
|
57
|
-
|
|
58
|
-
tokens:
|
|
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,
|
|
59
41
|
};
|
|
60
42
|
walk(ast as Node, state, {
|
|
61
43
|
_(node, { state, next }) {
|
|
62
|
-
|
|
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) {
|
|
63
56
|
const token: LeafToken = {
|
|
64
|
-
loc: node.loc
|
|
57
|
+
loc: node.loc!,
|
|
65
58
|
};
|
|
66
59
|
if ("isDummy" in node && node.isDummy) {
|
|
67
60
|
token.isDummy = true;
|
|
@@ -70,8 +63,9 @@ export function collectLeafTokens(ast: any): LeafToken[] {
|
|
|
70
63
|
token.generatedLength = 1;
|
|
71
64
|
}
|
|
72
65
|
state.tokens.push(token);
|
|
66
|
+
} else {
|
|
67
|
+
state.tokens.push(...subState.tokens);
|
|
73
68
|
}
|
|
74
|
-
next();
|
|
75
69
|
},
|
|
76
70
|
NewExpression(node, { state, next }) {
|
|
77
71
|
const lParenLoc = node.lParenLoc;
|
|
@@ -1,37 +1,28 @@
|
|
|
1
|
-
import type { AST } from "../../types";
|
|
1
|
+
import type { AST } from "../../types.ts";
|
|
2
2
|
import { walk } from "zimmerframe";
|
|
3
|
-
import type { SourceInfo, TranspileResult } from "
|
|
4
|
-
import { print } from "
|
|
3
|
+
import type { SourceInfo, TranspileResult } from "../index.ts";
|
|
4
|
+
import { print } from "espolar";
|
|
5
5
|
import {
|
|
6
6
|
initialTranspileState,
|
|
7
7
|
type TranspileOption,
|
|
8
8
|
type TranspileState,
|
|
9
|
-
} from "../gts";
|
|
10
|
-
import { gtsToTypingsWalker, type TypingTranspileState } from "./walker";
|
|
11
|
-
import { applyReplacements } from "./replacements";
|
|
9
|
+
} from "../gts.ts";
|
|
10
|
+
import { gtsToTypingsWalker, type TypingTranspileState } from "./walker.ts";
|
|
11
|
+
import { applyReplacements } from "./replacements.ts";
|
|
12
12
|
import type { Program } from "estree";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { patchedPrinter } from "./printer";
|
|
13
|
+
import { VERIFICATION_ONLY_MAPPING_DATA, type VolarMappingResult } from "./mappings.ts";
|
|
14
|
+
import { getPrintOptions } from "./printer.ts";
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
extraMappings: Map<string, string>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function gtsToTypings(
|
|
26
|
-
ast: AST.Program,
|
|
27
|
-
option: TypingTranspileOption,
|
|
28
|
-
): TranspileResult {
|
|
16
|
+
export function transformForVolar(
|
|
17
|
+
ast: Program,
|
|
18
|
+
option: TranspileOption,
|
|
19
|
+
sourceInfo: Required<SourceInfo>,
|
|
20
|
+
): VolarMappingResult {
|
|
29
21
|
const state: TypingTranspileState = {
|
|
30
22
|
...(initialTranspileState(option) as Pick<
|
|
31
23
|
TypingTranspileState,
|
|
32
24
|
keyof TranspileState
|
|
33
25
|
>),
|
|
34
|
-
leafTokens: option.leafTokens,
|
|
35
26
|
idCounter: 0,
|
|
36
27
|
typingPendingStatements: [],
|
|
37
28
|
rootVmId: { type: "Identifier", name: "__gts_root_vm" },
|
|
@@ -44,41 +35,50 @@ function gtsToTypings(
|
|
|
44
35
|
metaTypeIdStack: [],
|
|
45
36
|
finalMetaTypeIdStack: [],
|
|
46
37
|
attrsOfCurrentVm: [],
|
|
47
|
-
|
|
38
|
+
|
|
39
|
+
sourceNodes: new WeakSet(),
|
|
40
|
+
namedAttributeCalleeLParenRange: new WeakMap(),
|
|
41
|
+
literalFromIdentifier: new WeakSet(),
|
|
42
|
+
lastArgNodes: new WeakSet(),
|
|
43
|
+
diagnosticsOnTopNodes: new WeakSet(),
|
|
44
|
+
extraMappings: [],
|
|
48
45
|
};
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
// mark sourceNodes before the transformation
|
|
47
|
+
walk(ast as AST.Node, state, {
|
|
48
|
+
_(node, { state, next }) {
|
|
49
|
+
if (node.range) {
|
|
50
|
+
state.sourceNodes.add(node);
|
|
51
|
+
}
|
|
52
|
+
next();
|
|
53
|
+
},
|
|
52
54
|
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
sourceInfo: Required<SourceInfo>,
|
|
63
|
-
): VolarMappingResult {
|
|
64
|
-
const tokens = collectLeafTokens(ast);
|
|
65
|
-
const extraMappings = new Map<string, string>();
|
|
66
|
-
const { code, sourceMap } = gtsToTypings(ast, {
|
|
67
|
-
...option,
|
|
68
|
-
leafTokens: tokens,
|
|
69
|
-
extraMappings,
|
|
55
|
+
const newAst = walk(ast as AST.Node, state, gtsToTypingsWalker);
|
|
56
|
+
// mark lastArgNodes
|
|
57
|
+
walk(newAst as AST.Node, state, {
|
|
58
|
+
CallExpression(node, { state }) {
|
|
59
|
+
const lastArg = node.arguments.at(-1);
|
|
60
|
+
if (lastArg) {
|
|
61
|
+
state.lastArgNodes.add(lastArg);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
70
64
|
});
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
65
|
+
const printOptions = getPrintOptions(sourceInfo.content, state);
|
|
66
|
+
let { code, mappings } = print(newAst, printOptions);
|
|
67
|
+
code = applyReplacements(state, code, mappings);
|
|
68
|
+
for (const extraMapping of state.extraMappings) {
|
|
69
|
+
const genOffset = code.indexOf(extraMapping.generatedNeedle);
|
|
70
|
+
mappings.push({
|
|
71
|
+
sourceOffsets: [extraMapping.sourceOffset],
|
|
72
|
+
lengths: [extraMapping.length],
|
|
73
|
+
generatedOffsets: [genOffset],
|
|
74
|
+
generatedLengths: [extraMapping.generatedNeedle.length],
|
|
75
|
+
data: VERIFICATION_ONLY_MAPPING_DATA,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
78
|
return {
|
|
79
79
|
code,
|
|
80
|
-
mappings
|
|
80
|
+
mappings,
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
export type { VolarMappingResult } from "./mappings";
|
|
84
|
+
export type { VolarMappingResult } from "./mappings.ts";
|